2014-09-06 3 views
7

Я пытаюсь понять использование лямбды в ракетке, и я до сих пор неясно. Я понимаю, что они неназванные (анонимные) функции, но почему это так хорошо? Мне нужно получить доступ к моим функциям от других функций, так как бы я их назвал ??? Пожалуйста, объясните небольшую программу ниже и почему лучше использовать лямбда? Спасибо.Lambda in Racket Explained

; why is this better than below??? 
(define test 
    (lambda (x) 
    (lambda (y) 
     (+ x y)))) 

(define add27 
    (test 27)) 

; what's wrong with this??? 
(define (addTest x) 
    (+ x 27)) 

> (add27 2) 
29 
> (addTest 2) 
29 

ответ

10

В Ракетка (и других функциональных языках программирования) lambda s очень полезен, когда вы хотите передать, функцию одноразовый в линии в качестве параметра без определения его первого. Например, предположим, что мы хотим скомпоновать список чисел. Мы можем пойти длинный путь и определить square функции первого, а затем использовать map:

(define (square x) 
    (* x x)) 

(map square '(1 2 3 4 5)) 
=> '(1 4 9 16 25) 

... Или мы можем просто передать lambda, как это:

(map (lambda (x) (* x x)) 
    '(1 2 3 4 5)) 

=> '(1 4 9 16 25) 

Как вы можете видеть, существуют случаи, когда мы не нуждаемся в , необходимо указать для обозначения имени функции. Конечно, если процедура представлена ​​lambda будет повторно использоваться в нескольких частях, или если это рекурсивная, то имеет смысл дать ему имя (так что это уже не анонимно):

(define square 
    (lambda (x) (* x x))) 

Вышеуказанное эквивалентно первому определению square в начале. На самом деле первое определение - это просто синтаксический сахар, чтобы определить функцию, но в конце все функции lambdas!

Теперь посмотрим ваш пример. Здесь мы используем в несколько иной манере в lambda, а также служит примером, почему они полезны - мы не только определяем функцию, но возвращает функцию, а также:

(define test 
    (lambda (x) 
    (lambda (y) 
     (+ x y)))) 

Возможно, это будет немного яснее, если мы пишем это так (это эквивалентно, по указанным выше причинам):

(define (test x) 
    (lambda (y) 
    (+ x y))) 

Или еще короче - в Ракетке мы можем также использовать этот синтаксис для тех же целей:

(define ((test x) y) 
    (+ x y)) 

Это не то, что это лучше (или хуже) способ определить функцию - это совсем другая вещь! мы определяем процедуру, называемую test, которая получает в качестве параметра x и возвращает в результате новую анонимную функцию, которая, в свою очередь, получит в качестве параметра y. Теперь в этих строках:

(define add27 
    (test 27)) 

... мы называем test с x значением 27, который возвращает анонимную функцию, и мы имя, которые функционируют add27. Помните lambda, который был получен как параметр y? теперь, когда lambda был назван add27 - и это пример currying.Подумайте об этом: test это функция, которая используется для создания функций, которые добавляют фиксированное значение x для данного параметра y, что объясняет, почему это работает:

(add27 2) 
=> 29 

С другой стороны, эта функция всегда будет добавить 27 к его параметру без возможности его изменить:

(define (addTest x) 
    (+ x 27)) 

(addTest 2) 
=> 29 

Вы видите разницу? test позволяет нам генерировать новые функции, которые добавляют произвольное значение, тогда как addTest всегда добавляет фиксированное значение, 27. Что, если вы хотите добавить, скажем, 100? используя test это просто:

(define add100 (test 100)) 

Но addTest не может быть изменена, мы должны были бы написать новую функцию:

(define (addTest100 x) 
    (+ x 100)) 

Я надеюсь, что это проясняет вещи, не стесняйтесь задавать в комментариях любые дополнительные вопросы о моем ответе.

+1

Большое спасибо за это объяснение. Я все еще пытаюсь понять, как все это работает, но это отличное начало. Теперь мне просто нужно перечитать его 500 раз. =) – 1Raptor007

+0

Извините, но я все еще не понимаю, как это возвращает функцию. Я не понимаю. – 1Raptor007

+1

@ 1Raptor007 функция возвращает последнее значение. Например, это возвращает '1' при вызове:' (define (f) 1) '. И учитывая, что «лямбда» также является значением, как и любое другое, если мы напишем следующее: '(define (f) (lambda (x) x))', тогда у нас есть функция, которая при вызове вернется в результате анонимная функция –