development release version 9.0.21

Notices and updates
Locked
Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

development release version 9.0.21

Post by Lutz »

• a fix for a critical bug in 'match'. The bug was introduced in 9.0.17
• a new 'curry' function

files and 9.1 release notes: http://newlisp.org/downloads/development/

Lutz

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

It looks that new 'curry' works only on binary operators. Could we extend it to any number of parameters?

(define (f x y) (+ x y))
(curry f x) => (lambda (y) (f x y))

(define (f x y z) (+ x y z))
(curry f x) => (lambda (y z) (f x y z))

...

Thank you, Fanda

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

I thought about this, but it is too expensive performance wise. A built-in variable length 'curry' would be no advantage to a hand-written one.

In your example the number of arguments is visible from the 'define', but many time i.e. with '+' or functions written for variable number of arguments it is not visible. This means that append operations always have to be performed when applying the curried function, which would be a great performance penalty for binary curried ops.

Also in most situations you will use 'curry' to transform binary operators and functions into unary predicates for filtereing comparing etc. and than the gained speed is appreciated.

Lutz

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

I was playing with it and here are the 2 versions:

Version 1 that discoveres lambdas and macros and uses their parameter count:

Code: Select all

(define (curry f)
  (letex (f f cargs (args))
    (if (or (lambda? f) (macro? f))
      (append (lambda) (list ((length 'cargs) ((0 f) 0))) (list (append (list f) 'cargs ((length 'cargs) ((0 f) 0)))))
      (lambda () (apply f (append 'cargs (args)))))))
Version 2 which accepts the number of parameters explicitly:

Code: Select all

(define (ncurry n f)
  (letex (f f cargs (args))
    (if
      (= n 0) (lambda () (apply f (append 'cargs (args))))
      (> n 0) (letn (len-args (length 'cargs)
                     params (map sym (map string (dup "p" (- n len-args) true) (sequence (+ len-args 1) n))))
                (append (lambda) (list params) (list (append (list f) (append 'cargs params)))))
      (< n 0) (begin
                (set 'n (- n))
                (letn (len-args (length 'cargs)
                       params (map sym (map string (dup "p" (- n len-args) true) (sequence 1 (- n len-args)))))
                  (append (lambda) (list params) (list (append (list f) (append params 'cargs)))))))))

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

Examples:

Code: Select all

> (define (f x y) (+ x y))
(lambda (x y) (+ x y))
> (ncurry 2 f 1)
(lambda (p2) ((lambda (x y) (+ x y)) 1 p2))

> (ncurry 2 match ''(a *))
(lambda (p2) (match <40FDB2> '(a *) p2))
> (ncurry 2 ''match ''(a *))
(lambda (p2) (match '(a *) p2))

> (define (g a b c d) (+ a b c d))
(lambda (a b c d) (+ a b c d))
> (ncurry 4 g 1 2)
(lambda (p3 p4) ((lambda (a b c d) (+ a b c d)) 1 2 p3 p4))
> (ncurry -4 g 1 2)
(lambda (p1 p2) ((lambda (a b c d) (+ a b c d)) p1 p2 1 2))

> (ncurry 0 + 1 2 3 4 5)
(lambda () (apply + <40B4B5> (append '(1 2 3 4 5) (args))))
n = 0 => variable length
n = +c => left curry
n = -c => right curry

Locked