Когда использовать лямбда-определение с «голым» формальным параметром? - PullRequest
8 голосов
/ 11 января 2012

В данный момент я изучаю схему Guile, и в документации я неожиданно натолкнулся на следующую конструкцию:

((lambda args (display args)) 42)
=> (42)

Это заставило меня задуматься;До этого момента я предполагал, что формальные параметры всегда были заключены в список:

((lambda (args) (display args)) 42)
=> 42

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

((lambda args (display args)) 1 2 3)     => (1 2 3)
((lambda (. args) (display args)) 1 2 3) => (1 2 3)

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

Ответы [ 2 ]

6 голосов
/ 11 января 2012

Разница в том, что эта версия получает единственный параметр с именем args, который полезен для случаев, когда вы точно знаете число фактических аргументов, ожидаемых для формы lambda:

(lambda (args) (display args))

И этоверсия получает (возможно, пустой) список параметров, называемый args, полезный, когда вы ожидаете переменного числа аргументов для формы lambda:

(lambda args (display args))

Должно бытьнет разницы между следующими двумя версиями, но не все интерпретаторы примут вторую, так как в ней отсутствует часть перед точкой (поэтому ее следует избегать):

(lambda args (display args))
(lambda (. args) (display args))

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

(lambda (mandadory1 mandatory2 . optional) (display mandatory1))
1 голос
/ 27 января 2012

Это бросило меня в тупик; до этого момента я предполагал, что формальные параметры всегда заключались в список:

Обратите внимание, что такие вещи, как (a . args) и (a b . args), на самом деле тоже не списки. (a . args) - это пара, где car - это символ a, а cdr - это символ args. (a b . args) - это пара, где car - это символ a, а cdr - это (пара, в которой car - это символ b, а cdr - это символ args). Некоторое время это выглядит как список, с a и b и так далее, но так как он не заканчивается нулевым / пустым списком, это не совсем правильный список. Подобные структуры часто называют неправильными списками. Если вы хотите, вы можете прочитать немного о записи с точечной парой здесь или где-то еще ...

С (. args) Я бы сказал что-то вроде «это пара, где cdr - это символ args». Или, может быть, это получится как «пара, где car есть, а cdr - args». В любом случае это не имеет большого смысла, и, как сказал Крис Джестер-Янг, это не совсем правильная Схема.

Итак. Такие вещи, как (a b . args), являются просто обычными точечными парами для обозначения вещей, которые не равны нулю в последнем cdr. Если формальная вещь параметров в Схеме может быть одним из этих неправильных списков или надлежащим списком или просто символом, то определение формальной вещи параметров должно быть чем-то вроде: формальная вещь параметров должна быть нулевой, символом, или пара, где car является символом, а cdr является формальным параметром.

(Что я думаю, что это довольно крутая вещь, которая делает довольно элегантный способ привязки аргументов к параметрам. Например, вы смотрите на формальные параметры-вещи, и если это символ, вы привязываете список аргументов к этому и если это пара, вы связываете car аргументов с cdr формальной вещи-аргумента и повторяете cdr формальной вещи-аргумента / аргумента (о, и если это ноль, то вы, как и все, сделали или что-то в этом роде. Это кажется мне немного более красивым, чем в Common Lisp, "и если символ в car равен &rest, то вы привязываете остальные аргументы к символу после этого".)

...