aa
aa copied to clipboard
Named arguments
From Aaron: call with a struct instead of a tuple: (fun @{x=123,y=456}). Needs default args also.
Python uses a =
for optional argument and requires the non-default arguments at the end.
>>> f = lambda a=1, b: a+b
SyntaxError: non-default argument follows default argument
this is because they allow mixed calling f(1, b=2)
so positional arguments lose meaning after a left out optional
if an aa call is either a call by struct or a call by tuple this restriction may not be warented
f = {a, b=2, c=3 -> a + b + c}
f @{a=1} \\ 6
f @{a=1, b=4} \\ 8
f @{a=1, c=5} \\ 8
f @{a=1, b=4, c=5} \\ 10
f @{} \\ type error @{} !< @{a}
Looks good to me!
Usual question: what is the scope of the default expressions:
a=some_expensive_default;
g=2;
f = {a, b=g/*uses 'g=2' by default*/, c=a/*uses prior a and NOT argument a*/ -> a + b + c}
The expressions for 'a' and 'g' are not available at the call-site, so probably end up in a curried version of 'f' used by the default call sites.
Ahh... which leads me to the cost model: Default arguments are pre-computed at the function definition point, just in case a curried /default version is called. This cost can be further delayed until first-use by defining the default argument as a Future. 'aa' will not auto-Future default arguments without some sort of syntactic-sugar request.
I feel like this is just a special case of the scope within expressions. Whether it is a tuple, a struct, or a args what do we want the comma to mean?
If comma means strict sequential ordering
n = 0;
f = { -> n=n+1; n}
(f(),f(),f()) \\ (1, 2, 3)
@{a=f(), b=a, c=f()} \\ @{a=4, b=4, c=5}
or aa could not have the ordering
(f(),f(),f()) \\ non determanistic 1,2,3 in any order
@{a=f(), b=a, c=f()} \\ Error: a used before definition
The win of the first one is that I can build up a namespace
@{
func_a = { -> ...},
func_b = { -> ...},
func_c = { -> func_a() + func_b },
}
if the normal import is to eval the file and have the last form returned we can have a clean literal over
func_a = { -> ...}
func_b = { -> ...}
func_c = { -> func_a() + func_b }
@{func_a=func_a, func_b=func_b, func_c=func_c}
which is a clean way to do exports but not as clean as the ordered one.
'aa' as a whole is strictly deterministic, with parallelism coming some other (TBD) constructions.
Reasoning: easier to understand the meaning of code.
Commas separate arguments in a tuple (and otherwise have nothing to do with ordering).
Struct definitions definitely have order, and can be used to build up a namespace - and they use semi-colon not comma.
Reasoning: Most languages use semi-colon to end field definitions so lower weirdness budget to go with the crowd; and also this is the same grammar (and same parser) as the normal expression parsing, so again less mental budget to understand the code.