(f x y z)
Is equivalent to: (f . (x . (y . (z . ())))
Every function takes one argument - a list.Lists make partial application simpler than with tuples (at least Haskell style tuples), because we don't need to define a new form for each N-sized tuple. Eg, in Haskell you'd need:
partial2 : (((a, b) -> z), a) -> (b -> z)
partial3 : (((a, b, c) -> z), a) -> ((b, c) -> z)
partial4 : (((a, b, c, d) -> z), a) -> ((b, c, d) -> z)
...
With S-expressions, we can just define a partial application which takes the first argument (the car of the original parameter list) and returns a new function taking a variadic number of arguments (the cdr of the original parameter list). Eg, using a Kernel operative: ($define! $partial
($vau (f first) env
($lambda rest
(eval (list* f first rest) env))))
($define! f ($lambda (x y z) (+ x y z)))
(f 3 2 1)
=> 6
($define! g ($partial f 3))
(g 2 1)
=> 6
($define! h ($partial g 2))
(h 1)
=> 6
($define! i ($partial h 1))
(i)
=> 6
We could perhaps achieve the equivalent in Haskell explicitly with a multi-parameter typeclass and a functional dependency. Something like: class Partial full first rest | full first -> rest where
partial :: (full -> z, first) -> (rest -> z)
instance Partial ((a,b)) a b where
partial (f, a) = \b -> f (a, b)
instance Partial ((a, b, c)) a ((b, c)) where
partial (f, a) = \(b, c) -> f (a, b, c)
instance Partial ((a, b, c, d)) a ((b, c, d)) where
partial (f, a) = \(b, c, d) -> f (a, b, c, d)
...