I have more of an open question that explicit one.
In thinking about function declaration, I'm wondering how accurate is the following model:
<func | proc | method | iterator | converter> `<identifier>` [*]?
[ [ static[U]: StaticType = default_value, T: GenericType = default_type, ...] ]
( a : TypeDesc = default_type; [ var ]? b : GenericType = default_value, [ var ]? a : ConcreteType= default_value)
{. pragmas .} : [ var | const ]? <return_type> = ...body...
Are StaticType and ConcreteType ( e.g. int ) actually the same?
Do all types (TypeDesc, GenericType, ConcreteType) take type-classes?
type
EgConcreteType = int32 | int64
EgGenericType = int32 | int64
EgTypeDesc = typedesc[int32 | int64 ]
Is it possible (or even desirable / make sense) to return a TypeDesc from a function?
Would it make sense for StaticType to take a typedesc, instead of a value? Or is that what GenericType is for?
I feel like there is a simplification here somewhere that I'm not seeing
That type parameter syntax is really off, you can't have default values for generics and you don't define static types like static[U]: int. I also don't think const T is a valid return type
Static types essentially accept compile time constants and can be used in routine call/type parameters. I'll show code to explain because it's fairly simple.
proc foo1[T: static[int]](value: bool): array[T, bool] =
for i in 0..<T:
result[i] = value
let arr1 = foo1[3](true)
doAssert(arr1[2] == true)
proc foo2(length: static[int], value: bool): array[length, bool] =
for i in 0..<length:
result[i] = value
let arr1 = foo1(3, false)
doAssert(arr1[2] == false)
type A = static[int] # this works too, and you can replace static[int] usages with it
Typedesc is similar in that instead of being a compile time constant it's a compile time type, and is a way of moving type parameters into the call parameter list.
proc foo1[T](param: int) = discard
proc foo2(T: typedesc, param: int) = discard
foo1[Exception](5)
foo2(Exception, 5)
proc foo3[T: Exception](param: int) = discard
proc foo4(T: typedesc[Exception], param: int) = discard
foo3[IOError](5)
foo4(IOError, 5)
Recent versions of Nim have T: type Exception as sugar for T: typedesc[Exception] so don't be confused if you see that too.