Generic type alias syntax
tmteam opened this issue · comments
tmteam commented
Provide syntax to specify Generic arguments
Add any sintax to the candidate list. Comment any thoughts on any syntaxes
Candidates:
#'a of[b,c]' syntax
#'a:b, a[of b]' syntax
#'a of b, a [of b,c], [of] fun(...)' syntax
#'a:b, a{of b,c}' syntax
#'a:b, a<of b,c>' syntax
#'a:b, a of<b>' syntax
#'a:b, a of b, foo() of b' syntax
#'a<b,c>' syntax
#'a of(b,c)' syntax
#'a:b a<b,c>' syntax
#'a:b a:(b,c)' syntax
#'a()of[b,c]' syntax
#'a of b, a [of b,c], [of] fun(...)' syntax
a:optional of int = default
b = default of optional of int
w: array of optional of int = [1,2,none]
c = foo[of int](42)
c2 = foo(42) of int
d = foo[of optional of int,text](31,'test')
e:array of int = default
f = [1,2,3 of int]
g = [1,2,3] of real[]
h = cast x of int
i = (cast x) of text
j= cast [of int,text] x
k = x[of int].convert()
l = x.convert() of text
m= x.convert of [int,text]()
o = convert(x of[int])
p = convert(x) of[text]
q= convert of [int,text](x)
bar [of T] (a:T): optional of T = if(a==default) none else a
foo [of T1, T2](a:T1):T2 = if (T1>default) T1 else T2
[of T1, T2, where T1,T2 is <> ]
foo (a:T1, b:T2)
= if (T1>T2) T1 else T2
- to have two syntaxes - is not very consistent. May be implemented in future
- x[of int].foo() === (x of int).foo()
#' a of[b,c]' syntax
a:optional of[int] = default
b = default of[optional of int]
w: array of[optional of[int] = [1,2,none]
c = foo of[int](42)
c2 = of [int] foo(42)
d = foo of[optional of[int],text](31,'test')
e:array of[int] = default
f = [1,2,3 of [int]]
g = [1,2,3] of [real[]]
h = cast x of[int]
i = (cast x) of[text]
j= cast of [int,text] x
k = x of[int].convert()
l = x.convert() of[text]
m= x.convert of [int,text]()
o = convert(x of[int])
p = convert(x) of[text]
q= convert of [int,text](x)
bar of[T] (a:T): optional of[T] = if(a==default) none else a
foo of[T1, T2](a:T1):T2 = if (T1>default) T1 else T2
foo of[T1, T2](a:T1, b:T2) where { T1,T2 is <>}
= if (T1>T2) T1 else T2
#'a:b, a[of b]' syntax
a:optional[of int] = default
b = default:optional[of int]
w: array[of optional[of int]] = [1,2,none]
c = foo[of int](42)
c2 = foo(42):int
d = foo[of optional[of int],text](31,'test')
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast[of int,text] x
k = x:int.convert()
l = x.convert():text
m= x.convert[of int,text]()
o = convert(x:int)
p = convert(x):text
q= convert[of int,text](x)
bar[of T](a:T): optional[of T] = if(a==default) none else a
foo[of T1, T2](a:T1) :T2 = if (T1>default) T1 else T2
foo[of T1, T2: T1,T2 is <>](a:T1, b:T2)
= if (T1>T2) T1 else T2
#can be moved upper
[of T1, T2: T1,T2 is <>]
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
- default of T === default:T
- conflicts with slice operator [:step]
- a = x:int + x:uint - it is confusing
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
) - fooof T :T is nice
-+ a:array[of int] is special... - [] is easier to type
#'a:b, a{of b}' syntax
a:optional{of int} = default
b = default:optional{of int}
w: array {of optional {of int}} = [1,2,none]
c = foo{of int}(42)
c2 = foo(42):int
d = foo{of optional{of int},text}(31,'test')
e:array{of int} = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast{of int,text} x
k = x:int.convert()
l = x.convert():text
m= x.convert{of int,text}()
o = convert(x:int)
p = convert(x):text
q= convert{of int,text}(x)
bar{of T}(a:T): optional{of T} = if(a==default) none else a
foo{of T1, T2}(a:T1) :T2 = if (T1>default) T1 else T2
foo{of T1, T2: T1,T2 is <>}(a:T1, b:T2)
= if (T1>T2) T1 else T2
#may move upper
{of T1, T2: T1,T2 is <>}
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
- conflicts with slice operator [:step]
- default:T === default{of T}
- a = x:int + x:uint - it is confusing
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
) - foo(42) :T is nice. better than foo of syntax
- a:array{of int} is intuitive for C-like. 'of' adds readability
- very precise for complex notation before fun def
#'a:b, a of<b>' syntax
a:optional of<int> = default
b = default:optional<of int>
w: array<of optional<of int>> = [1,2,none]
c = foo of<int>(42)
c2 = foo(42):int
d = foo of<optional of<int>,text>(31,'test')
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast of <int,text> x
k = x:int.convert()
l = x.convert():text
m= x.convert of<int,text>()
o = convert(x:int)
p = convert(x):text
q= convert of <int,text>(x)
bar of<T>(a:T): optional of<T> = if(a==default) none else a
foo of<T1, T2>(a:T1) :T2 = if (T1>default) T1 else T2
foo of<T1, T2: T1,T2 is <>>(a:T1, b:T2)
= if (T1>T2) T1 else T2
- conflicts with slice operator [:step]
- default:int === default of
- a = x:int + x:uint - it is confusing
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
) - foo of(42) :T is nice
-+ a:array of is intuitive for C-like
- foo of ... is generally confusing because of spaces (spaces are not in nfun meta)
Syntax candidates to solving [a:b] problem
y = [1..4][0 to 3]
z = [1..4][0:int to 3:real step 5]
zz = [1..4][0 to 3 step 5]
yy = [1..4][to 3]
mm = [1..4][1 to]
mm = [1..4][1 to step 5]
y10 = [1..4][0 ... 3 step 5]
z10 = [1..4][0:int ... 3:real step 5]
yy = [1..4][...3]
mm = [1..4][1...]
mm = [1..4][1... step 5]
y3 = [1..4][0 :: 5]
z3 = [1..4][0:int :: 3:real step 5]
i3 = [1..4][:: 5]
f3 = [1..4][0::]
k3 = [1..4][0::step 5]
y5 = [1..4][0---5]
z5 = [1..4][0:int --- 3:real step 5]
i5 = [1..4][---5]
f5 = [1..4][0---]
k5 = [1..4][0--- step 5]
madY = y = [1..4][0..3]
madZ = [1..4][0..3 step 5]
madZ2 = [1..4][0,1,2,3]
wow1 = foo(:int,42) # we may send type here!
foo(t:type, a) = if a.getType() == type "it is" else "it is not"
#'a:b, a of b, foo() of b' syntax
a:optional of int = default
b = default:optional of int
w: array of optional of int = [1,2,none]
c = foo(42) of int
c2 = foo(42):int
d = foo(31,'test') of (optional of int,text)
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast x of (int,text)
k = x:int.convert()
l = x.convert():text
m= x.convert() of (int,text)
o = convert(x:int)
p = convert(x):text
q= convert(x) of (int,text)
bar(a:T) of T
: optional of T = if(a==default) none else a
foo(a:T1) of (T1, T2) :T2 = if (T1>default) T1 else T2
foo(a:T1, b:T2) of (T1, T2) { T1,T2 is <>}
:T1 = if (T1>T2) T1 else T2
- conflicts with slice operator [:step]
- default:int === default of int
- a = x:int + x:uint - it is confusing
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
)
- foo(42) of T :T is quite confusing. May be foo(42) {of int}?
+- foo(42) of T\r\n :T = is readable
#'a<b,c>' syntax
a:optional<int> = default
b = default<optional<int>>
c = foo<int>(42)
c2 = foo(42)<int>
d = foo<optional<int>,text>(31,'test')
e:array<int> = default
f = [1,2<int> 3 ]
g = [1,2,3]<real[]>
h = cast x<int>
i = (cast x)<text>
j= cast<int,text> x
k = x<int>.convert()
l = x.convert()<text>
m= x.convert<int,text>()
o = convert(x<int>)
p = convert(x)<text>
q= convert<int,text>(x)
bar<T>(a:T): optional<T> = if(a==default) none else a
foo<T1, T2>(a:T1):T2 = if (T1>default) T1 else T2
foo<T1, T2>(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
denies chain comparation
#'a of(b,c)' syntax
a:optional of(int) = default
b = default of(optional of(int))
w: array of(optional of(int)) = [1,2,none]
c = foo of(int)(42)
c2 = foo(42) of (int)
d = foo of(optional of int,text)(31,'test')
e:array of(int) = default
f = [1,2 of (int), 3 ]
g = [1,2,3] of (real[])
h = cast x of (int)
i = (cast x) of (text)
j= cast of (int,text) x
k = x of(int).convert()
l = x.convert() of(text)
m= x.convert of (int,text)()
o = convert(x of (int)
p = convert(x) of(text)
q= convert of (int,text)(x)
bar of(T)(a:T): optional of(T) = if(a==default) none else a
foo of(T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo of(T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
- mess in convert /case
#'a:b a<b,c>' syntax
a:optional<int> = default
b = default:optional<int>
w: array<optional<int>> = [1,2,none]
c = foo<int>(42)
c2 = foo(42):int
d = foo:optional<int,text>(31,'test')
e:array:int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast<int,text> x
k = x:int.convert()
l = x.convert():text
m= x.convert<int,text>()
o = convert(x:int)
p = convert(x):text
q= convert<int,text>(x)
bar:T(a:T): optional-<T> = if(a==default) none else a
foo:(T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo:(T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
y = [1..4][0:3 step 5]
z = [1..4][(0:int):(3:real) step 5]
- default:int === default
- conflicts with slice operator [:step]
- denies chain compare
- a = x:int + x:uint - it is confusing
- default:int === default
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
) - kotlin way :)
#'a:b a:(b,c)' syntax
a:optional:int = default
b = default:optional:int
w: array:optional:int = [1,2,none]
c = foo:int(42)
c2 = foo(42):int
d = foo:optional:(int,text)(31,'test')
e:array:int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast:(int,text) x
k = x:int.convert()
l = x.convert():text
m= x.convert:(int,text)()
o = convert(x:int)
p = convert(x):text
q= convert:(int,text)(x)
bar:T(a:T): optional-<T> = if(a==default) none else a
foo:(T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo:(T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
y = [1..4][0:3 step 5]
z = [1..4][(0:int):(3:real) step 5]
#'a()of[b,c]' syntax
a:optional of[int] = default
b = default of[optional of int]
w: array of[optional of[int]] = [1,2,none]
c = foo of[int](42)
c2 = foo(42) of int
d = foo of[optional of[int],text](31,'test')
e:array of[int] = default
h = cast x of [int]
i = (cast x) of [text]
j= cast of [int,text] x
k = x of [int].convert()
l = x.convert() of [text]
m= x.convert of [int,text]()
o = convert(x of [int])
p = convert(x) of [text]
q= convert of [int,text](x)
bar(a:T): optional of[T] of [T]
= if(a==default) none else a
foo(a:T1):T2 of [T1, T2]
= if (T1>default) T1 else T2
foo(a:T1, b:T2) of [T1, T2] where { T1,T2 is <>}
= if (T1>T2) T1 else T2
bar(a:T): optional of[T] of [T]
is a mess
not sure:
rejected:
#'a:b, {of b}' syntax
a:{of int}optional = default
b = default:{of int}optional
w:{of {of int} optional} array = [1,2,none]
c = {of int}foo(42)
c2 = foo(42):int
d = {of {of int}optional,text}foo(31,'test')
e:{of int}array = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= {of int,text}cast x
k = x:int.convert()
l = x.convert():text
m= x.{of int,text}convert()
o = convert(x:int)
p = convert(x):text
q= {of int,text}convert(x)
{of T}
bar(a:T): {of T}optional = if(a==default) none else a
foo{of T1, T2}(a:T1) :T2 = if (T1>default) T1 else T2
{of T1, T2: T1,T2 is <>}
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
- conflicts with slice operator [:step]
- a = x:int + x:uint - it is confusing
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
) - foo(42) :T is nice. better than foo of syntax
- a:array{of int} is intuitive for C-like. 'of' adds readability
- very precise for complex notation before fun def
- ugly for {of {of int} optional} array
#'a:b, a of b' syntax
a:optional of int = default
b = default:optional of int
c = foo of int(42)
c2 = foo(42):int
d = foo:optional:(int,text)(31,'test')
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast of (int,text) x
k = x:int.convert()
l = x.convert():text
m= x.convert of [int,text]()
o = convert(x:int)
p = convert(x):text
q= convert of [int,text](x)
bar of T(a:T): optional of T = if(a==default) none else a
foo of T1, T2(a:T1):T2 = if (T1>default) T1 else T2
foo of (T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
- conflicts with slice operator [:step]
- a = x:int + x:uint - it is confusing
- most intuitive for a:b reasons (but has some issues, like
a = x:int + x:uint
)
- foo of int(42) is quite confusing. May be foo(42) of int?
- foo of T1, T2(42) is hell
- foo of T1, T2(i:int) is bloody hell
#'a-<b a-<(b,c)' syntax
a:optional-<int> = default
b = default-<optional-<int>>
c = foo-<int(42)
c2 = foo(42)-<int
d = foo-<optional-<(int,text)(31,'test')
e:array<int> = default
f = [1,2-<int, 3 ]
g = [1,2,3]-<real[]
h = cast x-<int
i = (cast x)-<text
j= cast-<(int,text) x
k = x-<int.convert()
l = x.convert()-<text
m= x.convert-<(int,text)()
o = convert(x of (int)
p = convert(x) of(text)
q= convert of (int,text)(x)
bar-<T>(a:T): optional-<T> = if(a==default) none else a
foo-<T1, T2>(a:T1):T2 = if (T1>default) T1 else T2
foo-<T1, T2>(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
- ok, i try
#'of[b,c] a' syntax
a: of[int] optional = default
b =of[optional of int] default
c = of[int] foo(42)
c2 = of[int] foo(42)
d = of[optional of[int],text] foo(31,'test')
e:of[int] array = default
f = [1,2,of [int] 3 ]
g = of [real[]] [1,2,3]
h = cast of[int] x
i = of[text] cast x
j = # impossible
k = (of[int] x).convert()
l = of[text] x.convert()
m= x.of [int,text] convert()
o = convert(of[int] x)
p = of[text] convert(x)
q= of [int,text] convert(x)
of[T] bar(a:T): of[T] optional = if(a==default) none else a
of[T1, T2] foo(a:T1):T2 = if (T1>default) T1 else T2
of[T1, T2] where { T1,T2 is <>}
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
- is not better than
a of[b]
- absolute mess in convert/cast cases
#'a[b,c]' syntax
a:optional[int] = default
b = default[optional[int]]
c = foo[int](42)
c2 = foo(42)[int]
d = foo[optional[int],text](31,'test')
e:array[int] = default
f = [1,2[int], 3 ]
g = [1,2,3][real[]]
bar[T](a:T): optional[T] = if(a==default) none else a
foo[T1, T2](a:T1):T2 = if (T1>default) T1 else T2
foo[T1, T2](a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
- bad idea as it intesects with array access syntax
#'a-<b,c>' syntax
a:optional-<int> = default
b = default-<optional-<int>>
c = foo-<int>(42)
d = foo-<optional-<int>,text>(31,'test')
e:array<int> = default
f = [1,2-<int>, 3 ]
g = [1,2,3]-<real[]>
bar-<T>(a:T): optional-<T> = if(a==default) none else a
foo-<T1, T2>(a:T1):T2 = if (T1>default) T1 else T2
foo-<T1, T2>(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
- it crushes my eyes
#'a-<b,c>-' syntax
a:optional-<int>- = default
b = default-<optional-<int>->-
c = foo-<int>-(42)
c2 = foo(42)-<int>-
d = foo-<optional-<int>-,text>(31,'test')
e:array<int> = default
f = [1,2-<int>-, 3 ]
g = [1,2,3]-<real[]>-
bar-<T>-(a:T): optional-<T>- = if(a==default) none else a
foo-<T1, T2>-(a:T1):T2 = if (T1>default) T1 else T2
foo-<T1, T2>-(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
- it crushes both of my eyes
#'a of b, a of(b,c)' syntax
a:optional of int = default
b = default of optional of int
c = foo of int(42)
c2 = foo(42) of int
d = foo of(optional of int,text)(31,'test')
e:array of int = default
f = [1,2 of int, 3 ]
g = [1,2,3] of real[]
bar of T (a:T): optional of T = if(a==default) none else a
foo of (T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo of (T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
two syntaxes - looks not very consistent. May be implemented in future