LINUX.ORG.RU

баг или фича

 ,


1

1

Почитываю на досуге книжку «Интерпретация лиспа и scheme», Кристиана Кеннека, и обнаружил любопытную фразу:

Под влиянием лямбда-исчисления, в честь которого названа специальная форма lambda, LISP-1.0 был сделан динамическим, но вскоре Джон Маккарти осознал,что он ожидал получить от следующего выражения (2 3), а не (1 3):

(let((a 1))
((let((a 2))(lambda(b)(list a b)))
3))
Эта аномалия (неосмелюсь назвать её ошибкой)была исправлена введением новой cпециальной формы function. Она принимала lambda-форму и создавала замыкание...

В связи с этим сразу 2 вопроса:

1) Почему лямбда исчисление здесь ассоциируется с динамическим связыванием, а не лексическим, как сейчас принято считать в мейнстриме?
2) Почему автор считает это аномалией (и это мнение я вижу вообще часто в различных источниках), когда это совершенно нормальное поведение для динамического связывания. What a fucking «аномалия», это что как если бы НЛО прилетело? Неужели Маккарти был настолько туп, что это казалось ему «аномалией»?

С небольшими изменениями (illegal function call) на CL:

CL-USER> (let ((a 1))
	   (funcall (let ((a 2)) 
		      (lambda (b)(list a b)))
		    3))
(2 3)

Работает вполне очевидно.

Deleted ()
Ответ на: комментарий от Deleted

С небольшими изменениями

Что значит с небольшими? Я не знаю CL, поэтому заарнее прошу прощения, если чо, но по-моему у Вас из формы let возвращается уже готовый список, во внешней let уже ничего не биндится.

anonimous ()
Ответ на: комментарий от b0oh

Ну дык, это понятно. Вопрос то не в этом. У Вас обычное лексическое связывание здесь получается. Для лексического связывания это очевидное поведение, само-собой.

anonimous ()
Ответ на: комментарий от b0oh

anonimous

Что значит с небольшими?

Добавил лишь funcall, ибо в CL такой вызов функции не допустим.

b0oh

потому что в cl, динамический переменные создаются при помощи defvar или declare special

Ок. Не обратил внимание.

Deleted ()
Ответ на: комментарий от Deleted

Да речь о том, что у вас тут лексическое связывание а не динамическое. Из внутреннего let возвращается уже (2 3), во внешнем let биндить уже нечего.

anonimous ()
Ответ на: комментарий от anonimous

Да речь о том, что у вас тут лексическое связывание а не динамическое.

Уже понял свою ошибку.

Deleted ()
Ответ на: комментарий от anonimous

Нашел сейчас оригинал этого куска:

Under the inspiration of lambda-calculus, which loaned its name to the special form lambda, Lisp-1.0 was defined as a dynamic Lisp, but early on, John Mc-Carthy recognized, that he expected the following expressionto return (2 3) rather than (1 3) [code here]. That anomaly (dare we call it a bug?) was correctedby introducing a new special form? known as function. Its argument was a lambda form, and it created a closure...

На мой взгляд, переведено все абсолютно правильно, правда в самой фразе

Под влиянием лямбда-исчисления, в честь которого названа специальная форма lambda, LISP-1.0 был сделан динамическим, но вскоре Джон Маккарти осознал...

, может быть, содержится определенная неоднозначность, возможно это надо понимать как

Под влиянием лямбда-исчисления была названа специальная форма lambda.

а потом отдельно:

Lisp-1.0 был сделан...

, я хз, но не похоже.

anonimous ()

What a fucking «аномалия», это что как если бы НЛО прилетело? Неужели Маккарти был настолько туп, что это казалось ему «аномалией»?

Лол, просто он посчитал что это неприемлемо, вот и все. Как это работает он, очевидно, понимал.

Kuzy ★★★ ()
Ответ на: комментарий от Kuzy

что это неприемлемо

Не, ну а что неприемлимо, если динамическое связывание так работает? Так, и никак иначе. И все лиспы до scheme (20 лет), так были спроектированы, всех устраивало. И сейчас многие так.

anonimous ()
Ответ на: комментарий от anonimous

Не, ну а что неприемлимо, если динамическое связывание так работает? Так, и никак иначе. И все лиспы до scheme (20 лет), так были спроектированы, всех устраивало. И сейчас многие так.

А еще раньше одевались в шкуры и жили в пещерах. И всех все устраивало.

anonymous ()
Ответ на: комментарий от anonymous

А еще раньше одевались в шкуры и жили в пещерах. И всех все устраивало.

Вы, видимо, хотите сказать, что динамическое связывание устарело/плохое и прочее. Не буду спорить (хотя существуют альтернативные мнения - тот же RMS, к примеру), но к вопросу это не имеет отношения.

anonimous ()
Ответ на: комментарий от anonimous

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

anonymous ()
Ответ на: комментарий от Deleted

Добавил лишь funcall, ибо в CL такой вызов функции не допустим.

УМВР. Я имею в виду форму записи ((lambda () 4)), например. Хотя я сам так никогда не пишу, но clisp и sbcl это понимают

shamaz ()
Ответ на: комментарий от shamaz

Кстати, это стандарт в CL или нет?

В ISLisp, вроде, вполне можно так писать

shamaz ()
Ответ на: комментарий от anonymous

В ским можно вот так, в принципе попробовать:

(let((a 1))
((fluid-let((a 2))(lambda(b)(list a b)))
3))
В СL, я хз.

anonimous ()
Ответ на: комментарий от anonimous

Он не ожидал другого поведения, он просто решил, что ранее запроектированное поведение - говно.

anonymous ()
Ответ на: комментарий от anonimous

Сначала Маккарти считал, что бегать в шкурах на голое тело - норм. И сам иногда так бегал. Но потом осознал, что такое поведение - не то, чего можно ожидать от белого человека.

anonymous ()
Ответ на: комментарий от pseudo-cat

Ну да, я о том же, а как еще это можно воспринять. Похоже на отсебятину автора (не переводчика).

anonimous ()
Ответ на: комментарий от anonimous

Кстати, если верить Гаю Стиллу («Lisp and Interpreters»), Маккарти не старался изначально копировать лямбда-исчисление.

contrarry to popular belief, Lisp was not originally derived from Church's lambda-calculus [ Church ] [ Lisp History ].

anonimous ()
Ответ на: комментарий от shamaz

УМВР. Я имею в виду форму записи ((lambda () 4)), например. Хотя я сам так никогда не пишу, но clisp и sbcl это понимают

Так и у меня работает, а в случае ТС:

CL-USER> (let((a 1))
	   ((let((a 2))(lambda(b)(list a b)))
	    3))

; in: LET ((A 1))
;     ((LET ((A 2))
;        (LAMBDA (B) (LIST A B)))
;      3)
; 
; caught ERROR:
;   illegal function call

;     (LET ((A 1))
;       ((LET ((A 2))
;          (LAMBDA (B) (LIST A B)))
;        3))
; 
; caught STYLE-WARNING:
;   The variable A is defined but never used.
; 
; compilation unit finished
;   caught 1 ERROR condition
;   caught 1 STYLE-WARNING condition
; Evaluation aborted on #<SB-INT:COMPILED-PROGRAM-ERROR {C787C11}>.
Deleted ()

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

Потому что Маккарти был малограмотен.

Miguel ★★★★★ ()
Ответ на: комментарий от Miguel

Потому что Маккарти был малограмотен.

Смешно, учитывая то, что он отец функционального программирования.

Однако же здесь речь идет о мнении не столько Маккарти, сколько самого автора книги. А что касается Маккарти, он видимо, вообще не забивал голову етим вопросом: баг или фича (комментарий)

anonimous ()
Ответ на: комментарий от anonimous

хотя существуют альтернативные мнения - тот же RMS, к примеру

Уже ж выпиливают dynamic binding из емакса потихоньку. По крайней мере, lexical binding уже в 24 версии костылями сумели прибить.

Corey ()
Ответ на: комментарий от Corey

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

anonimous ()
Ответ на: комментарий от anonymous

Ваш пример некорректен. Он при любом связывании выдаст (2 3)

anonimous ()
Ответ на: комментарий от anonimous

Смешно, учитывая то, что он отец функционального программирования.

Ну, он сам признавался, что лямбда-исчисление не понял.

Miguel ★★★★★ ()
Ответ на: комментарий от Miguel

Да и вообще современный взгляд на ФП - это какой то прадокс

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

Чем отличается явное хранение от неявного? Тем, что я не лезу в неявные скопы, неявные состояния. Либо это не позволяет сам язык, либо я сам не хочу лезть - и не лезу. Или сам обеспечиваю инкапсуляцию, если боюсь влезть случайно. ЯП тут вообще не при чем.

anonimous ()
Ответ на: комментарий от Miguel

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

anonimous ()
Ответ на: комментарий от anonimous

А пруф можно?

Можно.

http://www-formal.stanford.edu/jmc/history/lisp/node2.html — из книги самого Маккарти:

«To use functions as arguments, one needs a notation for functions, and it seemed natural to use the -notation of Church (1941). I didn't understand the rest of his book...»

Пропущена греческая «лямбда». Книга, о которой идёт речь — Church, Alonzo (1941) The Calculi of Lambda Conversion.

Да и вообще современный взгляд на ФП - это какой то прадокс

То, что ты привёл — не «современный взгляд на ФП», а какая-то хренотень. И уж точно к ООП имеет большее отношение, чем к ФП. С какой помойки ты эту цитату вытащил?

Miguel ★★★★★ ()
Ответ на: комментарий от Miguel

and it seemed natural to use the -notation of Church

Ну правильно, я так и подумал, это как раз соответствует моему замечанию

баг или фича (комментарий)

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

anonimous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.