development release version 9.0.21

Started by Lutz, February 08, 2007, 07:49:58 AM

Previous topic - Next topic

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/">http://newlisp.org/downloads/development/



Lutz

Fanda

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

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

#3
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)))))))))

Fanda

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