Personally I would prefer to simplify the concept syntax.
From the current syntax:
type
Comparable = concept x, y
(x < y) is bool
To something like:
type
Comparable[T] = concept
proc `<`(x, y: T): bool
This would naturally extend to runtime interfaces:
type
Comparable[T] = interface
proc `<`(x, y: T): bool
As far as I know @zah has his reasons for not wanting to simplify the syntax this way. But yes, it's about time to have this discussion so thank you for bringing it up.
Agreed with GULPF: the imperative syntax of concepts makes it more suited to some kind of duck typing. Moreover, I find
type
Comparable = concept x, y
(x < y) is bool
simpler than
type
Comparable[T] = concept
proc `<`(x, y: T): bool
(if anything it is at least less verbose)
What if < is implemented with a template?
What if I don't want the concept to match in that case? The syntax I propose makes the specification significantly more concrete and therefore more reliable.
But by far the most significant advantage is that it makes the implementation far simpler. Concepts as they are right now are very ambitious and I don't trust them enough to make use of them because of this.
IMO, Concept syntax is great from the user perspective. It clearly describes what concept can do. From the implementer pointer of view it look like it is far too easy to miss concept requirement and you are not sure while writing the code you are matching the concept or not.
I don't think what you describe as declarative is going to work, because procs are not attached to type in Nim, they are freestanding and can be implemented in a different module then type is declared. Therefore you can't say if type is matching a concept or not by looking at a type definition. Developer can write in a separate file an adaptor to match the concept separately from actual object type. I don't have to rewrite objects to match a concept and it is a big win in my opinion.
What is missing is a simple proc concept_check that can at compile time check if concept is matched or not and the location of the mismatch. Developer can invoke it in the right place, usually after the procs not at a type def.
P.S. I think we should stop bitch and moan regarding concepts. Concepts are GREAT until someone find courage to implement something better. You are not happy with the concepts? Go and invest your next 9-16 months in a better solution. Once you have implemented it we can compare.
The problem with concept is that it doesn't work with seq[C]. If you're not aware of that, you can spend a huge amount of time debugging. After you're aware, you have to modify your API in potentially difficult ways.
Other than that, I think they're awesome. Not kidding. I love the syntax.
For more discussion, see https://forum.nim-lang.org/t/2999#25214
The concept syntax has been discussed already ad nauseam. The current syntax is inspired by the ConceptsLite proposal that will eventually make its way into C++, so in a distant future it should be familiar to a lot of people.
Considering that the concept definitions will be roughly 0.0005% of all Nim code ever written, I find it a bit strange that everyone spends so much time arguing about the peculiarities of the syntax. With concepts, it's the thousands of functions written to accept concept parameters that are important, not the syntax used in the definition of the concept. We should focus on the semantics of what can be expressed in a concept rather than how the syntax looks like (obviously, beauty here is in the eye of the beholder).
But anyway, here is one of my previous attempts to shot down alternative syntax proposals:
https://github.com/nim-lang/Nim/issues/5770#issuecomment-298886380
static:
assert Foo is SomeConcept
Future versions of Nim will produce a nice error message describing which concept requirement wasn't satisfied.
@arnetheduck, regarding run-time polymorphism, there is a planned feature called "VTable types". You can read the spec here:
https://github.com/nim-lang/Nim/blob/5491f1f53b4011785b41b30897b73538d564fd55/doc/manual.rst#L4764
@cdunn2001 I just replied to your other thread about concepts. I'm not seeing the issue you were mentioning.
I don't think it is a good idea to be explicit about < being a proc. For me concepts are about (static) duck typing: if it supports <, then it satisfies the concept. This is good, because I will want to call < on members of the type. I see concepts as a promise that the code I write next will compile when specialized.
I don't really care if < is a template or a proc, or possibly it is defined on a different type but a < b still compiles because of converters.