Какой смысл лямбда в схеме? - PullRequest
26 голосов
/ 31 мая 2010

Я изучаю схему. Я знаю, как использовать как лямбда-выражения, так и выражения let.

Однако я изо всех сил пытаюсь выяснить, в чем смысл использования лямбды. Разве вы не можете делать все с помощью Lambda?

Было бы особенно полезно увидеть пример ситуации, когда лямбда-выражение является лучшим выбором, чем let.

Еще одна вещь - есть ли ситуации, когда let более полезен, чем лямбда? Если так, то такой пример был бы также хорош.

Редактировать: Меня также интересуют контрасты define и lambda, поскольку они, похоже, выполняют аналогичные задачи.


Обновление:

Спасибо за помощь всем. После прочтения ваших ответов я еще немного изучил лямбду / let / define и теперь понимаю это намного лучше.

Я наткнулся на отличный пример использования лямбды - возвращение анонимных функций из процедур. Например, процедура operateTwice ниже возвращает анонимную функцию, основанную на параметрах, переданных в процедуру:

(define operateTwice
  (lambda (op1 op2)
    (lambda (x y)
      (op2 (op1 x y) y))))

((operateTwice * +) 2 3) ;equivalent to: (+ (* 2 3) 3), or in standard notation 2*3+3

Выход:

9

Ответы [ 6 ]

44 голосов
/ 31 мая 2010

A let является lambda.

* 1005 Е.Г. *

(let ((x 1))
  body)

можно перевести на

((lambda (x) body) 1)

Кроме того, на Схеме все структуры управления и среды могут быть представлены лямбда-выражениями и приложениями лямбд.

Итак, lambda является строго более мощным, чем let, и составляет основу многих интересных конструкций, найденных на Схеме.

Относительно define и lambda, верхний уровень define добавляет привязку к среде верхнего уровня.

Когда вы пишете

(define (f x)
  body)

Вы действительно говорите

(define f (lambda (x) body))

Вложенные определения переводятся в letrec, который также может быть переписан с использованием лямбд.

Итак, опять же, многие конструкции Scheme могут быть переведены во что-то, используя lambda, и поэтому действительно стоит хорошо понимать lambda.

14 голосов
/ 31 мая 2010

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

Например, если вы хотите добавить 42 к каждому номеру в списке, вы можете сделать:

(define (add42 x) (+ x 42))
(map add42 (list 1 2 3 4))

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

(map (lambda (x) (+ x 42)) (list 1 2 3 4))
4 голосов
/ 17 декабря 2011

Пусть на самом деле просто сокращение для лямбда-выражения. Следующие два выражения эквивалентны:

(let ((alpha 7)) (* 5 alpha))

((lambda (alpha) (* 5 alpha)) 7)

Лямбда следует философии языка, согласно которой все должно выглядеть как математическая функция. Но на практике Let позволяет легче понять, что происходит, если слишком много переменных. Представьте себе 10 переменных, значения которых определены после блока Lambda, и вы пытаетесь сопоставить каждую из них с именем переменной с помощью параметра Пусть значения переменных располагаются рядом с их именами, что удобно для программиста, но меньше соответствует функциональному Философия программирования.

Лямбда может использоваться для возврата функции из функции более высокого порядка, но пусть это не может быть сделано. Например:

(define (plus-list x)
  (cond ((number? x)
         (lambda (y) (+ (sum-n x) y)))
        ((list? x)
         (lambda (y) (+ (sum-list x) y)))
        (else (lambda (x) x))
        ))

> ((plus-list 3) 4)
10
> ((plus-list '(1 3 5)) 5)
14
> ((plus-list 'a) 5)
5

Лямбда также может использоваться для передачи функции в функцию:

>(map (lambda (x) (+ 1 x)) '(-1 2 -3))
(0 3 -2)
3 голосов
/ 31 мая 2010

В Схеме процедура (или функция) - это объект первого класса, такой как список, число или строка. Для создания списка литералов вы используете примитив list:

> (define marks (list 33 40 56))
> marks
> (33 40 56)

Точно так же, чтобы создать процедуру, вы используете примитив lambda (или специальную форму):

> (define add-marks (lambda (m) (apply + m)))
> (add-marks marks)
> 129

Поскольку процедуры являются основной формой абстракции, Scheme предоставляет ярлык для define, чтобы упростить привязку новых процедур:

> (define (add-marks m) (apply + m))

Кроме этого, процедуры аналогичны всем другим объектам первого класса. Они могут быть переданы в качестве аргументов другим процедурам, и процедура может выполнить оценку для создания (или возврата) другой процедуры.

3 голосов
/ 31 мая 2010

lambda создает новые анонимные функции, которые, конечно, оцениваются при каждом их использовании.

let создает временные имена для значений и устанавливается один раз для использования в области, определенной формой let.

Они действительно очень разные звери.

некоторые примеры:

(лямбда (х) (* 5 х))

(пусть ([x 2]) (* 5 x)) 10 (пусть ([f (лямбда (x) (* 5 x))]) (f 2)) 10

первая форма создает функцию для умножения на 5

вторая форма присваивает 2 x и умножает его на 5, что приводит к 10

в-третьих, мы используем функцию 1 (которая умножается на 5) и вызываем ее с 2 в качестве параметра, что также приводит к 10

1 голос
/ 31 мая 2010

Вы можете думать так ... вы создаете функцию, которая использует другую функцию но вы хотите сделать вещи более модульными, поэтому вы вызываете вторую функцию в качестве аргумента первой, и это дает вам возможность изменить вторую, когда вы чувствуете, что вам нужна другая функциональность ... надеюсь, что это имеет смысл

...