tmteam / NFun

Expressions Evaluator for .NET

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generic type alias syntax

tmteam opened this issue · comments

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