The following program generates an error. Shouldn't it work?
proc readMe[T](name: string): T =
result = 123'u16
var num = "test".readMe[uint16]()
# var num = readMe[uint16]("test")
echo num
Here are the error messages:
t.nim(5, 17) template/generic instantiation from here
t.nim(2, 13) Error: cannot instantiate: 'T'
The workaround is to use the commented out line instead.
This works
proc identity[T](name: T): T =
result = name
var n1 = "test".identity
var n2 = 123.identity
echo n1
echo n2
It's a known issue. It's hard to disambiguate "test".readMe[uint16]() with a bracket expression I suppose since at that time the compiler doesn't know if uint16 is a typedesc or an index I suppose.
I think there is a RFC for that: https://github.com/nim-lang/Nim/issues/3502
Never liked using a special bracket character for generic type parameters.
# this is not a "generic procedure", it's a procedure constructor.
proc threeOf[A](a: A): array[3, A] =
for i in 0 .. 2:
result[i] = a
# the procedure constructor is called with a type parameter to *produce* a proc.
var p = threeOf[int]
# then, the proc is called with a value parameter.
echo p(5)
The fact that the constructor call can happen at compile time and sometimes the type parameter can be implied doesn't change that. IMHO it would make more sense to use parentheses for type parameters, because that's what we use for parametrization anyway:
proc threeOf(A)(a: A): array(3, A) = ...
threeOf(int)(5)
Type and value parameters are distinguishable by the case of the leading character or - for builtins - by syntax highlighting. Square brackets are reserved to indcate indexing, as they should.
Edit: replaced the square brackets in array[3, A] with parentheses too.
@Lando: that would create ambiguities:
proc test(x: typedesc): proc(x: int) =
(proc(x: int) = echo x)
proc test(A)(x: int) =
echo x
test(int)(123) # which one is it?
Personally, I also think it looks far uglier.@StasB: The first definition is just a complicated way to write the second one. typedesc parameters make a proc generic, just like square bracket parameters (apart from special binding behaviour). And yes, that's an ambiguity and therefore should result in a compiler error.
About the ugliness: you have a point here, but I find consistency far more important (Haskell changed my mind quite a bit).
The first definition is just a complicated way to write the second one.
Huh. Looks like you're right:
proc test(T: typedesc): proc(x: T) =
(proc(x: T) = echo x)
test(string)("foo")
Never occurred to me that you can use it this way.
I find consistency far more important (Haskell changed my mind quite a bit).
Then you should be disturbed by the fact that Haskell's type system corresponds to an inconsistent logic. ;^)