Hi Guys,
I need your help. In the past two weeks I spent roughly 30 hours debugging the
compiler to add proper `concept[T]` support. It feels like I'm at half of the
work. Now I'm stuck at a language design question, how to find out `T` in
`concept[T]`. I don't have a good proposal. Please take some time to think
about this. I really should go back to push my regular work, so I'm trying to
close this issue as soon as possible.
When you read the following examples then you might think that these are easy
questions, and the compiler should be smart enough. Please keep in mind that we
eventually want to use `concept[T]` for types like `Map[ Map[int, string],
Map[seq[Map[int, int]], float]]`. Also, the main motivation is to create a
function like `proc getKeyWithLowestValue[K,V]( map: Map[K,V] ): K` which could
work on multiple map implementation (like HashMap, TreeMap in Java).
So let's start with the current stage. If you write this:
type StrangeConcept[T] = concept c
c is T # Equivalent to "c is any", which is true
float(c) is T # Equivalent to "float(c) is any", which is true
$c is T # Equivalent to "$c is any", which is true
when int is StrangeConcept:
echo "Yes, it is" # this is printed
So `c is T` doesn't assign `T`, right? This could be fixed, however, should the
following work?
type NewConcept[T] = concept c
c is seq[T]
...
One could say that yes, the compiler should be smart enough to find out `T` in
this example. However, if `c` is a `seq[seq[int]]`, then `T` should be
`seq[int]` and not `seq[any]` or `any`. Fair enough. Let's continue:
type YouCanAddOne[T] = concept c
c is T
c+1 is T
What should we do in a case like this? The first line assigns `T`, and the
second line is actually a testing? Am I the only one who feels this extremely
strange? What happens if you swap `c is T` and `c+1 is T`? Then `T` is assigned
by the type of `c+1`? Do we want the order to matter? (I know, it doesn't
matter in this example.)
Let's continue the examples:
type MixWithFunctions1[T] = concept c
f[T](c)
...
type MixWithFunctions2[T] = concept c
f(c, (new T)[])
...
Shall we support something like these? I truly believe that we shouldn't. Just
imagine that this needs backtrack algorithms because multiple `f` function can
match. That would slow down the compiler (but it would become a constraint
solver :) ).
Somewhat cleaner approach:
type ShouldBeClearConcept[T] = concept c
type T = type( c[0].getFirstValue() )
...
This is easy to follow, there is no hidden logic. This way we wouldn't abuse
our little `is` magic operator for something nesty with assignment. However,
defining `T` after we already wrote `T` in `ShouldBeClearConcept[T]` is not
very elegant and it is not in line with the rest of the language design. Please
keep in mind that you cannot miss assigning `T`, because `proc f[S](c:
ShouldBeClearConcept[S]): S` needs to know about it.
What's your opinion?
Cheers,
Peter