When I saw recently that Lutz had added curry as a new intrinsic procedure, I thought "way cool!" (I still think that, BTW.)
But apparently, you can't curry a function using more than one (curry) argument:
> (define (f x y z) (* x (+ y z)))
> (define f-2-3 (curry f 2 3))
> (f-2-3 4)
value expected in function + : z
called from user defined function f
called from user defined function f-2-3
However, you can define, as a macro, your own curry functor which fixes this (you've seen this before, e.g. from John Small):
(define-macro (currie f)
(letex ($f (eval f)
$cargs (map eval (args)))
(lambda () (apply $f (append (quote $cargs) (args))))))
> (define f-2-3 (curry f 2 3))
> (f-2-3 4)
14
So, I'd like for Lutz to consider changing the intrinsic curry to handle this situation. Then I can get rid of currie! :-)
I second this.
Originally 'curry' was coded like Rick's currie, but for efficiency reasons I went to the simpler curry for only two functions arguments. The current curry has only the lambda overhead:
(curry func arg) => (lambda (_x) (func arg _x))
With the current one I wanted a fast currying function for usage primarily in 'find' and 'clean' for binary ops and without the additional overhead of the apply- and append operations necessary in a general curry
Perhaps we should have a second 'curry-nth' which can take more arguments and could additionally have an index parameter telling which parameter of the funtion should be curried?
Lutz
That sounds good. I just wish there were a useful way to do it recursively, because I really like the sound of "recurry" ;)
Anyone spare a few moments to explain in simple terms why curry (also known as "Schönfinkelisation" if the Wikipedia is to be believed) is useful? When would I use it?
Hi cormullion!
The following is from the WikiP article you mentioned:
Quote
The practical motivation for currying is that very often the functions you get by supplying some but not all of the arguments to a curried function are useful; for example, many languages have a function or operator similar to plus_one. Currying makes it easy to define these functions.
In newLISP:
> (set '+one (curry + 1))
(lambda (_x) (+ 1 _x))
> (+one 2)
3
> _
Useful? Maybe, but as Lutz said earlier, it's primarily used with the 'find' and 'clean' functions.
m i c h a e l
It's a fast way of applying a lambda when you know what the first argument should be every on every application. If you wanted to add 10 to every number in '(1 2 3 4 5), you could do:
(map (lambda (n) (+ n 10)) '(1 2 3 4 5))
Or, you could do:
(map (curry + 10) '(1 2 3 4 5))
While this doesn't save a lot of time on that small example, when performing more complex applications, curry can save a heck of a lot of time.
Quote from: "Jeff"
It's a fast way of applying a lambda when you know what the first argument should be every on every application.
that's a good way of putting it. I shall steal that phrase for the next iteration of the "introduction to newlisp" (credited of course :-)
The one that sprung to mind immediately was:
(set 'blank (curry dup " "))
cos I'm often writing this...
Quote from: "m i c h a e l"
The following is from the WikiP article you mentioned:
I propose that curry be renamed schönfinkelize, though.
Since many people are used to 'curry' accepting any number of arguments , I would make:
curry - any number of arguments
curry1 - accepting 1 to 4 arguments - special functions for speed optimization
curry2
curry3
curry4
Fanda
Quote from: "Fanda"
Since many people are used to 'curry' accepting any number of arguments , I would make:
curry - any number of arguments
curry1 - accepting 1 to 4 arguments - special functions for speed optimization
curry2
curry3
curry4
Fanda
Good!
Quote from: "Lutz"
Perhaps we should have a second 'curry-nth' which can take more arguments and could additionally have an index parameter telling which parameter of the funtion should be curried?
I like the idea of an index parameter:
(define (curry-nth n f)
(letex (n n f f cargs (args))
(lambda () (apply f (append (0 n (args)) 'cargs (n (args)))))))
(define f (curry-nth 1 explode 2))
(f "newLISP") => ("ne" "wL" "IS" "P")
(define f (curry-nth 1 explode 2 true))
(f "newLISP") => ("ne" "wL" "IS")
(define f (curry-nth 0 explode "apple"))
(f 2) => ("ap" "pl" "e")
(f 2 true) => ("ap" "pl")
(define f (curry-nth 1 append '(x y)))
(f '(a)) => (a x y)
(f '(a b)) => (a b x y)
(f '(a b) '(c d)) => (a b x y c d)
Fanda