Определение схемы/сокращение лямбда

В Scheme, как я могу использовать сокращение define/lambda для вложенных лямбда-выражений в моем определении?

Например, при следующей процедуре...

(define add
  (lambda (num1 num2)
    (+ num1 num2)))

Можно сократить это до этого:

(define (add num1 num2)
  (+ num1 num2))


Однако, как я могу сократить следующую функцию аналогичным образом?

(define makeOperator
  (lambda (operator)
    (lambda (num1 num2)
      (operator num1 num2))))

;example useage - equivalent to (* 3 4):
((makeOperator *) 3 4)

person Cam    schedule 31.05.2010    source источник


Ответы (3)


(define (makeOperator operator)
  (lambda (num1 num2)
    (operator num1 num2)))

Вторую лямбду можно не укорачивать.

Ну, вы можете сократить его до (define (makeOperator operator) operator), если вы не хотите, чтобы возвращаемая функция принимала ровно два аргумента.

person sepp2k    schedule 31.05.2010
comment
Спасибо - я поставлю вам +1, как только мой лимит голосов будет сброшен :). scheme.com/tspl2d/start.html#g1642 — при прокрутке вниз немного, автор, кажется, говорит о каком-то точечном синтаксисе для сокращения определений. Есть идеи, о чем он говорит? - person Cam; 31.05.2010
comment
@incrediman: Да, он говорит о (define (f . xs) ...), который позволит вам вызывать f с произвольным количеством аргументов (например, (f 1 2 3 4 5)), а xs будет списком, содержащим эти аргументы. - person sepp2k; 31.05.2010
comment
Ааа. Попался - спасибо. Это на самом деле очень полезно само по себе, поэтому я рад, что спросил :) - person Cam; 31.05.2010

Некоторые реализации Scheme, такие как Guile (протестировано с версией 1.8) и MIT Scheme, предоставляют следующую сокращенную запись:

(define ((foo x) y) (+ x y))

(foo 5)
; => procedure
((foo 5) 3)
; => 8

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

person Michał Marczyk    schedule 01.06.2010

Вопреки приведенному выше ответу, второй lambda может использовать сокращенную запись define:

(define (makeOperator operator)
  (define (foo num1 num2)
    (operator num1 num2))
  foo)
person Eli Barzilay    schedule 31.05.2010
comment
Это не совсем одно и то же. В моем более простом сокращении никакие дополнительные переменные не объявляются, но здесь вы объявляете foo. Поэтому, хотя он и использует синтаксис определения, на самом деле это не сокращение. Плюс она длиннее, чем лямбда-версия от sepp2k. /end относительно необразованное мнение - person Cam; 31.05.2010
comment
(a) я не сказал, что он короче — только то, что он использует стенографическую define форму, о которой вы спрашивали; (b) ваш вопрос заключался в том, можно ли использовать эту нотацию для внутреннего lambda -- очевидно, это будет связано с дополнительным именем, потому что это именно то, что делает define: его невозможно использовать без имени. - person Eli Barzilay; 01.06.2010
comment
О, и, кстати, если ваша цель состоит в том, чтобы просто сделать его коротким, то, как сказал sepp2k, вы можете использовать (define (makeOperator operator) operator), и если вы действительно хотите пройти весь путь: (define makeOperator values) примерно то же самое. - person Eli Barzilay; 01.06.2010
comment
@Eli: я думаю, что он, возможно, искал что-то вроде (define ((makeOperator operator) num1 num2) operator num1 num2), то есть определения каррированной функции, которого нет в схеме (но, вероятно, его можно было бы реализовать с помощью макроса). - person sepp2k; 01.06.2010
comment
@ sepp2k: Да, это то, что я искал - спасибо. @Eli: Если подумать, это действительно довольно хорошо отвечает на мой вопрос, хотя это не совсем то, что я искал, поэтому +1. Также я понимаю, что мой тривиальный пример можно упростить :) Спасибо. - person Cam; 01.06.2010
comment
@incrediman: Да, я думал, это помогло бы прояснить разницу. Кроме того, я подозреваю, что определение карри, которое упомянул sepp2k (и которое Михал превратил в ответ), ближе к тому, что вы хотели бы - но если вы находитесь на этом уровне изучения языка , лучше этого пока избегать. Это только внесет путаницу. (И вы можете легко вернуться к нему, когда будете говорить более бегло.) - person Eli Barzilay; 01.06.2010
comment
@Eli В связи с этим обсуждением можно ли исключить использование одной или обеих лямбд в определении permute в этом ответ? - person lifebalance; 06.06.2012
comment
@lifebalance: Да - обратите внимание, что обычно вы всегда можете превратить lambda в define, но результат будет более подробным, поэтому на практике это бесполезно. Реальный смысл этого в том, что вам не нужны анонимные функции, чтобы иметь язык с первоклассными функциями - и на первый взгляд, lambda можно определить как макрос, использующий define. - person Eli Barzilay; 06.06.2012
comment
@Eli Многословие также иногда делает его более читабельным? Не могли бы вы показать мне, как переписать permute без лямбда-выражений? Спасибо, - person lifebalance; 06.06.2012
comment
@lifebalance: это не сработает в комментарии, пришлите мне электронное письмо, и я объясню больше. (Или, может быть, начать новый вопрос, если это проще.) - person Eli Barzilay; 06.06.2012