В Ракетка (и других функциональных языках программирования) 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))
Я надеюсь, что это проясняет вещи, не стесняйтесь задавать в комментариях любые дополнительные вопросы о моем ответе.
Большое спасибо за это объяснение. Я все еще пытаюсь понять, как все это работает, но это отличное начало. Теперь мне просто нужно перечитать его 500 раз. =) – 1Raptor007
Извините, но я все еще не понимаю, как это возвращает функцию. Я не понимаю. – 1Raptor007
@ 1Raptor007 функция возвращает последнее значение. Например, это возвращает '1' при вызове:' (define (f) 1) '. И учитывая, что «лямбда» также является значением, как и любое другое, если мы напишем следующее: '(define (f) (lambda (x) x))', тогда у нас есть функция, которая при вызове вернется в результате анонимная функция –