> I concur that this awfully look like interfaces even> though you seem reluctant to give them that name.

Concepts are not like interfaces, such as Java's "interface" keyword: Concepts tell something about a type, whether that type is a built-in/fundamental type (like "int") or a user-defined type (for languages where there are no fundamental types, everything being a class, there may be less of a difference in this regard, but there are other ones, as noted below). To take a an example: Say you have a concept Addable, which is defined like this (made-up syntax, but similar to the C++ concept proposals):

concept Addable{ Element operator+(Element,Element);}

This concept can be matched ("modeled", in "concept speak") by types such as "int", "float", "SomeClassWithOverloadedOperatorPlus", etc.

In other words, there's no "interface" you derive from, to declare conformance to a concept, and as such, it can be used for built-in types, as well. Moreover, the above signature is a "pseudo-signature": A concept with a signature like "bool something()" can be modeled by a type with a function with the name "something", but it doesn't have to return exactly bool: it can return something _convertible_ to bool.

As Christopher writes in the blog, a concept also covers other aspects (such as semantics and complexity guarantees): "A concept is a description of a type, including functions signatures, preconditions, postconditions, invariants, and member types."

Bottom line: It's definitely not the same as inheritance. :) The matching is done based on syntax and semantics, not based on having to inherit from the same class (an interface, in Java, at least, is similar to a class with only pure virtual functions, in C++).

> I do want to support both concepts and interfaces though I> fear the subtle differences may just add too much> confusion. If I start sacrificing performance in terms of> flexibility, then I wonder, am I not going to end up> reinventing something Python-esque?I doubt you will, Pythonistas don't even bother with that kind of things, interfaces and concepts don't exist in Python but in some very specific structures/implementations (I think the Zope guys created interfaces, but Zope is often defined as one of the most un-pythonic python projects)

Now about your problem, I see a bit more precisely what you mean.

If you allow generics/templates in heron, then it becomes very simple: just use them

Something akin to foo(T:Stack x, T:Stack y) that could mean "variables of the T type considered on their Stack Concept (or interface) subset"The inner code of foo would see both x and y as Stacks, but the compiler would have checked (at compile time) for template type matching. The colon is of course an example and should be changed if you already use it a lot of feel it unclear.> To take a an example: Say you> have a concept Addable, which is defined like this> (made-up syntax, but similar to the C++ concept> proposals):> > concept Addable> {> Element operator+(Element,Element);> }> > This concept can be matched ("modeled", in "concept> speak") by types such as "int", "float",> "SomeClassWithOverloadedOperatorPlus", etc.> > In other words, there's no "interface" you derive from, to> declare conformance to a concept, and as such, it can be> used for built-in types, as well. Moreover, the above> signature is a "pseudo-signature": A concept with a> signature like "bool something()" can be modeled by a type> with a function with the name "something", but it doesn't> have to return exactly bool: it can return something> _convertible_ to bool.

That definition of a concept horribly sounds like strangely statified duck-typing that doesn't want to accept it's nature

> > Why is that a problem at all? If I want to ensure that> > the type parameters are of the same type, why muck> around> > with concepts and force the types to be the same? > > I can't figure out how to answer this question other than> to say: sometimes it is often useful to say "give me two> arguments of the same type, and that type should behave> like a stack". It happens all over the place in the STL.

In C++, with unconstrained template parameters (i.e. the only thing that exists, absent support for concepts), such templates are, as you know, written as:

> > To take a an example: Say you> > have a concept Addable, which is defined like this> > (made-up syntax, but similar to the C++ concept> > proposals):> > > > concept Addable> > {> > Element operator+(Element,Element);> > }> > > > This concept can be matched ("modeled", in "concept> > speak") by types such as "int", "float",> > "SomeClassWithOverloadedOperatorPlus", etc.> > > > In other words, there's no "interface" you derive from,> to> > declare conformance to a concept, and as such, it can> be> > used for built-in types, as well. Moreover, the above> > signature is a "pseudo-signature": A concept with a> > signature like "bool something()" can be modeled by a> type> > with a function with the name "something", but it> doesn't> > have to return exactly bool: it can return something> > _convertible_ to bool.> > That definition of a concept horribly sounds like> strangely statified duck-typing that doesn't want to> accept it's nature

The problem with duck typing is that you can't specify any constraints in the interface; it matches everything, and only potentially crashes in the implementation, not at the call-site, where the error arguably are (incompatible types used for the arguments). That's where "concepts", or "constrained generecity" (which is also found in some other languages, like Ada, Haskell and ML) come in, as they allow you to specify the constraints a type must meet, that may be checked at the call site (or instantiation site, for class templates).

Templates (and Herons concepts, I assume) are matched at compile-time, while in dynamically typed languages, the matching usually happens at run-time.

I'm wondering what you mean by "its nature", because it seems to me different terms are used for the same thing, and/or have different meaning to different people, making discussions confusing. The terms I used above, and Christopher uses, like "concept", "refinement" and "model", are specific terms in "generic programming" terminology, that I used to try to avoid misunderstandings. Of course, that's only successful if the terms are understood by others, as well. :)

Therefore, we may be talking about the same thing (and not something "trying to escape its nature" :) ), but I guess it goes to show that "duck typing" may mean different things to different people.

Assuming you define it this way, then how can you actually have a problem with the comparable interface? Any contrived examples? I can't think of any...

Your lt function should compile for 2 instances of the same type. And shouldn't for others, unless perhaps there's a conversion between the types.

As for iterator pairs... Typically you have a begin, and an end, which must be of exactly the same type, and in fact refer to the same container. I don't know if you can check whether they refer to the same container, but whether your function compiles or not should be a consequence of whether the equality test concept exists between the 2 iterators - and if it doesn't, you just catch any problems at compile time, don't you?

As for stacks... well, swap_tops should either just compile or not depending on whether or not x::element is convertible to y::element.

> Assuming you define it this way, then how can you actually> have a problem with the comparable interface? Any> contrived examples? I can't think of any...

Perhaps another example can highlight the differences between concepts and interfaces (i.e. inheritance from an interface). Here's a C++ example:

template<class T>void f(const T &t){ t(123);}

This would all compile and work, for T being:

- A function- A pointer to function- An object with an overloaded function call operator

How are you going to express that, using interfaces? The same goes for other operators, where the type may be a built-in type, or a user-defined type with operator overloading.

With support for concepts in C++, you might do this:

concept CallableWithInt{ void operator(int); // Pseudo-signature}

template<CallableWithInt T>void f(const T &t){ t(123);}

Use:

function g(int) {}

f(g);

void (*f_ptr)(int)=g;

f(f_ptr);

class test{ void operator()(int) {}}

test t;

f(t);

f(123); // This will give an error about the argument not being compatible with the concept, and the error message will come here at the call site (where it belongs), rather than from inside the function, like in the first, non-concept version.

> Assuming you define it this way, then how can you actually> have a problem with the comparable interface? Any> contrived examples? I can't think of any...

A comparable interface (ala Java) would require dynamic type-casting. This is inefficient. This is not neccessarily a "big deal", but it does represent the core difference between the two approaches. I honestly like both interfaces and concepts. If you look at my old blogs, you see that I keep jumping back and forth between the two. One of the many reasons Heron hasn't been visibly progressing in the last month.

I'm sorry, I confused the issue by saying 'interface' when I meant Heron concepts. And answers to my question seem to miss the mark. I'm not convinced that you have a syntax problem, because I think the current semantics of concepts probably provide enough safety.