Haskell-style Partial Application
Posted: Sun Nov 21, 2010 11:58 am
Okay, I've been using Lisp for a few months now, and I love the language, but recently I tried Haskell and I really like some of the features. I don't think I'll necessarily need the type system, but I really like the curried functions, because it makes mapping very easy. So, I decided I'd write a reader macro to implement Haskell-style partial application.
There is a long but not especially relevant story associated with this; more to the point, though, it ends with a system that works for &optional parameters but fails for &rest. (&key is not supported yet, but I don't think it will be very hard.) This would be semi-acceptable as a start, except that my initial reason for undertaking this was so that I could write (for example) "[+ 10]" instead of "(lambda (x) (+ x 10))", and as most of you probably know, #'+ accepts &rest arguments. I have a plan for adding this, but it involves a list that is two levels of backquote deeper than the surrounding list. Specifically, I can almost write
But this gives a form that evaluates to the form I want (which is to say, the form that the macroexpander should return, which should itself evaluate to an anonymous function), and if I remember correctly it's bad style to call eval explicitly. Are macroexpanders different, or should I rewrite this so it's not an issue? (If the latter, I'll probably need a complete rewrite. =/)
(Also, it seems moderately likely that some explanation is needed for the functions and variables I've defined. Informally, they do what their names say; more precisely, curry-lambdalist transforms a function's lambda list into a lambda list that has already accepted num-supplied-args arguments and handles &rest and &optional correctly; the fetch-* things take an arglist (for clarity, not shown) and return a list of the symbols representing the required, optional, and rest arguments; and fn is the function that was called at the toplevel.)
There is a long but not especially relevant story associated with this; more to the point, though, it ends with a system that works for &optional parameters but fails for &rest. (&key is not supported yet, but I don't think it will be very hard.) This would be semi-acceptable as a start, except that my initial reason for undertaking this was so that I could write (for example) "[+ 10]" instead of "(lambda (x) (+ x 10))", and as most of you probably know, #'+ accepts &rest arguments. I have a plan for adding this, but it involves a list that is two levels of backquote deeper than the surrounding list. Specifically, I can almost write
Code: Select all
`(lambda ,(curry-lambdalist full-arglist num-supplied-args)
`(funcall ,fn ,@(fetch-required) ,@(fetch-optional) ,@,(fetch-rest)))
(Also, it seems moderately likely that some explanation is needed for the functions and variables I've defined. Informally, they do what their names say; more precisely, curry-lambdalist transforms a function's lambda list into a lambda list that has already accepted num-supplied-args arguments and handles &rest and &optional correctly; the fetch-* things take an arglist (for clarity, not shown) and return a list of the symbols representing the required, optional, and rest arguments; and fn is the function that was called at the toplevel.)