newLISP Fan Club

Forum => newLISP newS => Topic started by: Lutz on February 08, 2007, 07:49:58 AM

Title: development release version 9.0.21
Post by: Lutz on February 08, 2007, 07:49:58 AM
• 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
Title:
Post by: Fanda on February 09, 2007, 04:58:44 AM
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
Title:
Post by: Lutz on February 09, 2007, 05:19:33 AM
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
Title:
Post by: Fanda on February 09, 2007, 08:34:18 AM
I was playing with it and here are the 2 versions:



Version 1 that discoveres lambdas and macros and uses their parameter count:
(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:
(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)))))))))
Title:
Post by: Fanda on February 09, 2007, 08:37:14 AM
Examples:
> (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