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

Reply via email to