-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
removing automatic currying #1026
Comments
The other thing that would need to change is that the type |
Making currying explicit suggests a scala-like syntax when we want to make defs with multiple params:
This allows a bit of a nicer syntax for the cases where you do want currying. A common performance reason for currying is when you can match on the first argument one time and then return different functions for different matches. This means that you don't re-run the match in each call. For instance:
The optimizer already moves matches closed-over values outside of the lambda to take advantage of that. Having the syntax above would be a nice syntax that doesn't block the optimization. |
There is a connection to struct/enum size here, which I overlooked: since constructors are just normal functions, they have to have types, so that means if you limit to functions of N args, you have to limit to structs of N args. If you want to be able to implement something like fast immutable vectors, then you will want a 32 factor of branching likely. This suggests a limit of 8 is too small. But writing out 32 function types in the predef.bosatsu, seems annoying, so maybe go back to programmatically adding all the Fn types. |
Some
So then you can do things like |
The current representation of functions is that there is only
a -> b
. We encodedef foo(a: a, b: b) -> c:
asa -> b -> c
. Like Haskell.This creates two challenges:
So, instead of copying Haskell, we would be more like scala 2 and have fixed sized Functions, say up to size 8 or something. (Haskell 98 requires tuples up to size 15, and standard functions up to size 7). It sometimes said humans can remember 7 plus or minus 2 things at one time. Choosing 8 is more than 7, and a power of two.
So, then we would require applying all the arguments of a function at once, or we would fail the type check because we would try unifying with the wrong arity of function.
There are three syntactic forms of function application:
foo(a, b)
a.foo(b)
Normal application wouldn't change, except that it wouldn't be auto-currying. You would need to manually curry if you want that with e.g.
x -> foo(y, x)
But for the dot apply, we need to change things. Plausibly,
a.foo(b)
could desugar tofoo(a)(b)
orfoo(a, b)
. Since the latter is more in-keeping with the ideas here, we have to deal with the fact thata.foo
can't be a valid value, since(a.foo)(b)
would then be different from(a.foo(b))
if we use the second desugaring. Therefore, we need to bana.foo
and requirea.foo()(b)
for the case which is the same asfoo(a)(b)
. Again, very arguably, this is more in keeping with the bosatsu way: if we have a function application it always has a()
.For the final case, left apply, I can see two possibilities: always expand into a function1, or allow some way of encoding the args. Since we already have
(x, y) <- ...
meaning pattern matching on expecting 1 arg which is a tuple, and that seems right, I wouldn't want to change that. One possibility would be to havex, y <- ...
, without parens, to mean a 2 argument function. This however is a little weird since in python it is the,
that creates the tuple. Also the lambda syntax already uses(x, y) ->
to mean a function2. Maybe the same rule should apply here and if you want to pattern match on a tuple, you use an extra layer of parens:((x, y)) <- ...
. That would be consistent with the lambda syntax, which the<-
is supposed to invoke anyway.I'm inclined to make this change as I've been thinking more and more about actually generating code that performs well and having explicit function arities, while possibly unmotivated purely by theory of lambda calculus, is very well motivated by the goal of running this code on existing CPUs or language VMs.
The text was updated successfully, but these errors were encountered: