Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
366 views
in Technique[技术] by (71.8m points)

lambda - Going from Curry-0, 1, 2, to ...n

Following up from a previous question I asked about writing a curry function, How to create a make-curry function like racket has, I've started writing the fixed case for 0, 1, 2 -- they are very similar to Church Numerals which is pretty neat. Here is what I have so far:

(define (curry-0 func)
  func)

(define hello (begin (display "Hello!") (newline)))
(curry-0 hello)
; Hello!
(define (curry-1 func)
  (lambda (x)
      (func x )))

((curry-1 -) 2)
; -2
(define (curry-2 func)
  (lambda (x)
    (lambda (y)
      (func x y))))

(((curry-2 +) 2) 3)
5

The pattern seems to be:

(define curry-n func
     (lambda (x1)
        (lambda (x2)
           ...
            (lambda (xn)
                (func x1 x2 ... xn)

However, I'm having some trouble 'building up' the n-nested lambda expression. I suppose I could build a nested lambda with something like:

(define (curry-n num func)
     (if (num > 0)
         (lambda (?) (curry-n (- num 1) func))))

But I'm not sure how I would 'bind' the variables to each lambda function and also how I would end up passing those same variables (in order) to the (func x1 x2 ... xn) function.

This is incorrect but I've started along the lines of...

(define (curry-n num func)
 (if (> num 0)
      ; but lambda won't accept a number, possible to string-format?
      (curry-n (- num 1) (lambda (num)))))

How could this be done?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The other answers may be a bit more efficient as they accumulate a concrete list of parameters, or fancier because they allow you to take multiple arguments at once, but in my opinion it is a better learning exercise, and simpler, to just write a basic function that takes one argument at a time with no need for an accumulator.

(define (curry n f)
  (cond ((= n 1) f)
        (else (lambda (x)
                (curry (- n 1)
                       (lambda args
                          (apply f (cons x args))))))))

 > (((curry 2 +) 5) 4)
=> 9

Instead of accumulating parameters, we just create a new lambda that expects fewer parameters each time, and curry that. It behaves very much like the generalization of your attempts for fixed n. It's the same basic approach as rawrex's (perfectly reasonable) answer, but without the fancy facility to handle args in larger chunks.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...