Wishlist Item: Improve curry

Started by rickyboy, May 22, 2007, 07:56:48 PM

Previous topic - Next topic

rickyboy

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! :-)
(λx. x x) (λx. x x)

Jeff

#1
I second this.
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

Lutz

#2
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

Jeff

#3
That sounds good.  I just wish there were a useful way to do it recursively, because I really like the sound of "recurry" ;)
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

cormullion

#4
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?

m i c h a e l

#5
Hi cormullion!



The following is from the WikiP article you mentioned:


QuoteThe 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

Jeff

#6
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.
Jeff

=====

Old programmers don\'t die. They just parse on...



http://artfulcode.net\">Artful code

cormullion

#7
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...

cormullion

#8
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.

Fanda

#9
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

rickyboy

#10
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!
(λx. x x) (λx. x x)

Fanda

#11
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