Hi Guys,
Sorry for disappearing for two weeks, it was due to the increase load at work.
I read through the Concepts manual proposal on Github. It is a long manual with
clear descriptions and examples. Congrats! The rest of my post might feel
negative a bit, but I'm really happy with this progress.
Here are some comments.
Peter
**1**:
> Within the concept body, types can appear in positions where ordinary values
> and parameters are expected.
I'm against this. I understand this is very handy, I can clearly see that the
examples are easy to follow, and I know that this is only the syntax. And I can
live with this if everybody thinks that this is the right way. However, it
makes an extra twist in the language. I think that Python is great because you
can do almost everything after learning about list, tuple and dict. Lisp is so
powerful, because once you accept its dummy function syntax `(+ 1 2)`, you can
modify your code from code. That is why I'm against any special treatment in
concepts: if I (finally learn how to) generate code from a tempate/macro, then
I cannot use exactly the same language for concepts.
> In order to check for symbols accepting `typedesc` params, you must prefix
> the type with an explicit `type` modifier.
(Sorry, I'm going to be mean here just to make a point.) Following this logic
should this code:
AdditiveMonoid* = concept x, y, type T
x + y is T
...
be something like this?
AdditiveMonoid* = concept x, y, type T
x + y is type T
...
Or the `is` magic is an exception from this rule?
**2**:
proc transpose*[R, C, T](m: AnyMatrix[R, C, T]): m.type.basis[C, R, T] =
for r in 0 .. <m.R:
for c in 0 .. <m.C:
result[r, c] = m[c, r]
What is `basis` here?
(Very unimportant comment, just some words about this example: we can have a
(very inefficient) matrix implementation which stores the elements in an SQL
database, or just simple on the heap. Is it ok not to initialize the result
here? The `AnyMatrix` concept suggest that we must have it on the stack with an
`Array` object (only the order can be different, e.g., Fortan vs C). So how
about adding an `m.init()` to the concept, and a `result.init()` just before
setting the values?)
**3**:
Unbound types can appear both as params to calls such as s.push(T) and on
the right-hand side of the `is` operator in cases such as x.pop is T and x.data
is seq[T].
and later
type
MyConcept = concept x
type T1 = auto
x.foo(T1)
x.bar(T1) # both procs must accept the same type
Please don't. First, I still find it very strange that we overload the `is`
operator. But having any function calls to infer types looks very dangerous. If
you still think that this is the way to go, then please answer the following
questions:
What happens if we have several `proc foo(x: ..., a: ...)` and `proc bar(x:
..., b: ...)` functions, do the compiler find a type in common? What happens if
there are more than one type in common? (It has to be unique, just think that
you can access this type from outside if it is generic.) Can I break a concept
match by adding a new function? What happens if I have `proc foo(x:..., a:
auto)`? Or let's twist it, I can have `proc foo(x:..., a: seq[any])`, what
happens there? If I have `foo` functions which eat 8 different types, then can
I force the compiler to find a way to put 8 queens on the chess board not
attacking each other? How fast will it be? Can we force it to return the first
in lexicographic order, or is it going to be random/all?
**4**:
In the example of _Converter type classes_, there are `Stringable` and
`makeStringRefValue`. These symbols are given only once (you are creating a
concept, which is not used, you are calling a function which is not defined).
Is this on purpose?
Is everything used for the calculation has to be after the `return` keyword?
Can you do some precalculation before the `return` line? I guess not, because
those lines are used for the concept check. Let me point out again that before
return this is valid, and after return this is not valid: `x.f(string, float)`.
**5**:
I can't comment on _VTable types_. I guess using this I could have a function
which actually eats many types, but still have one implementation in C which
does the type check at runtime. Sounds awesome in some cases, and very
complicated. I'm not sure that we can afford this complication at this point,
but I haven't seen the code for this.