LINUX.ORG.RU

Классификация операторов в Lisp

 


3

1

Разработчики Common Lisp не зря поменяли традиционный термин «специальная форма» на «специальный оператор». Например, выражение как целое (quote a) является специальной формой, а quote обозначает специальный оператор. Необходимо еще немного прояснить терминологию. Итак, оператор — любой объект, который может находится в голове формы. Ниже представлена классификация операторов:

                           Операторы
             _________________/\__________________________________________
	    |                              |                              |
         Функции                Специальные операторы                  макросы
       ____/\____              ____________/\________________ 
      |          |            |                              |
 встроенные   замыкания     Примитивные                 реификаторы
                        специальные операторы       ________/\_________
                                                   |                   |
                                               частичные             полные

Как можно видеть, я не отношу макросы к категории специальных операторов, т.к. макросы лишь эмулируют специальные операторы.

В соответствии с этой теорией должен быть изменен apply/eval интерпретатор:

(eval выражение окружение продолжение)
(apply-operator оператор аргументы окружение продолжение)
(apply-function функция аргументы продолжение)

Функция eval лишь вычисляет голову формы, а результат (оператор) классифицируется функций apply-operator, которая либо передает управление функции, которая реализует соответствующий специальный оператор, либо функции apply-function. Кроме того, что специальные операторы применяются к невычисленным аргументам (cdr формы), они еще имеют доступ к полному контексту вычислений. Макросы не имеют такого доступа, поэтому, я не классифицирую их как специальные операторы. Функции не имеют доступа к лексическому окружению момента вызова. Следовательно такие функции как set из CL должны рассматриваться как нарушение теории и исключены из Лиспа. Функция set может быть, но только если она будет принимать дополнительный аргумент: (set символ значение окружение).

Частичные реификторы. nlambda получает только cdr формы, vau — cdr формы и окружение.

Полные реификаторы. В работах Brian Cantwell Smith были предложены 3-х аргументные fexpr'ы. В реификаторы Смита передаются не только сырые аргументы и окружение, но и продолжение. Полные реификаторы неотличимы от встроенных специальных операторов.

Ответ на: комментарий от komputikisto

Lisp — одна из моделей (наряду с лямбда-исчислением) для научного исследования языков программирования. Если тебя языки интересуют лишь в практическом отношении, то Lisp тебе не нужен.

Многое теряешь если так думаешь. CL создавали, использовали и используют как раз махровые практики которым абсолютно не интересно что такое «реификатор» и вообще теория программирования как класс.

seg-fault
()
Ответ на: комментарий от bogus_result

Но возможно сама модель вычислений с окружениями создала проблему

Да, как известно, компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали. Кроме модели с окружением есть еще подстановочная модель как в лямбда-исчислении. Я не рассматриваю ее всерьез как модель описывающую языки программирования. Во-первых, это алгоритмическая модель, а как показал Peter Wegner алгоритмы не то же самое, что программы. Из-за этого возникли некоторые misconception при разработке функциональных языков. Например, предпочтение нормального порядка редукций вытекает из тезиса Тьринга-Чёрча, который был раскритикован Wegner'ом. Во-вторых, лямбда-исчисление основано на строках, а для языков программирования важны объекты и идентичность.

komputikisto
() автор топика
Ответ на: комментарий от hotpil

Я программирую. Зачем? Чтобы программы писать. Кому что, как говорится.

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

RUBY — это мощнейший язык, он ничем не уступает лиспам, скорей, даже, превосходит их. Это лисп и смоллток в одном флаконе

Руби не превосходит лиспы. Руби - это всего лишь смоллтолк для бедных.

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

попсовые — схему и cl — превосходит наголову. От смолтока он не особо отличается, в том смысле, что он содержит внутри себя смоллток как подмножество.

PS И вы заипали называть лиспами это недоалгольное убожество — кл и схему. Про нормальные лиспы речи нет тут. Но они здохли, чо за них тереть? поттора человека в мире прогают на picolisp, это язык? А руби жив пока.

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

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

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

ты надеешься своим тяфканьем привлечь чье-то внимание? разве что «отлюбленный 5 раз» прибежит, потяфкаете вместе. На внимание белых людей не расчитывай.

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

Я надеюсь, что ты переосмыслишь своё существование, но я зря трачу время

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

Видимо, достопочтенный анон имел в виду, что питон скопип*дил жабскую модель ООП. А правда, интересно, почему его все называют «динамическим» языком? Что в нем динамичного? Типизацию не берем, с ней все ясно, но разве этого достаточно, чтобы говорить о динамичности языка?

anonymous
()

Два чая этому шизофренику. Прочитал тред с удовольствием.

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

Судя по тому, что я читаю, лексического связывания там нет. Но есть shadowing (как это по-русски, когда связываешься с тем же символом, а по выходе из блока переменная возвращает своё значение). А чтобы ой-ой не дай бог не затереть значение, связанное с тем же символом, который выступает аргументом функции, используются какие-то transient symbols. Это то, что я щас успел нагуглить.

Причём автор не честен как минимум. Он сравнивает производительность своего лиспа с common lisp, использую clisp, который в сотни раз медленнее sbcl

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

У него есть тесты и с SBCL, где последний сосет. Но дело там не в перформансе, по большому счету, а в том, что picolisp — это олдскульный тру лисп без свистоперделок, компилтайм макросов и прочего говна.

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

Я не об этом и я не прикалываюсь😊 Вы никогда не думали насчет того, что должна существовать модель вычислений, в которой легитимны оба варианта:

(set (some-kind-of-quote x) <value>)

(setq x <value>)

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

Я это к тому, что окружение как набор связываний имён со значениями слишком просто устроено. Отсюда и исходят проблемы. Я же не против модели вычислений с окружениями😊

Делай все настолько просто, насколько возможно, но не проще. Помните кто сказал?

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

что должна существовать модель вычислений

Это ты перебрал с «моделью»

легитимны оба варианта:

Ну так в нормальных лиспах так оно и есть, setq просто сахар для set, без квотирования. В CL чо, не так чтоле?

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

Есть большое подозрение, что функция set должна быть легитимной не в том виде, который вы привели:

(set (quote x) <value> environment)

а в другом виде:

(set (some-kind-of-quote x environment) <value>)

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

Понятно, что в CL она легитимна. ТС же заявляет о нелегитимности функции set в том виде, в котором она существует, и приводит другой её вид.

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

И если мы правильным образом определим специальный оператор some-kind-of-quote то нам не понадобится передавать окружение явно для его вычисления (это следует из идей ТС).

Остается единственный вопрос - должны ли быть quote и some-kind-of-quote одним и тем же специальным оператором? Я сходу сказать не могу, но подозреваю, что нет.

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

У него есть тесты и с SBCL, где последний сосет.

Рассказывай, да

niemand
()

Функции не имеют доступа к лексическому окружению момента вызова. Следовательно такие функции как set из CL должны рассматриваться как нарушение теории и исключены из Лиспа.

Так set и не имеет доступа к лексическому окружению:

* (let ((n 1)) (set 'n 2) n)
1
* n
2

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

setq просто сахар для set, без квотирования. В CL чо, не так чтоле?

Не так. set всегда работает с toplevel

* (let ((n 1)) (setq n 2) n)

2
* (let ((n 1)) (set 'n 2) n)

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

питон ... А правда, интересно, почему его все называют «динамическим» языком? Что в нем динамичного?

Возможность переопределения функций, классов. Интроспекция по отношению к объектам, классам, типам, ...

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

в которой легитимны оба варианта:

Если считать, что (set 'x ...) и (setq x ...) одно и то же, то set обязан быть специальным оператором (как и setq).

monk ★★★★★
()

Резонёрство — «склонность к бесплодному мудрствованию», «словесная опухоль» (И. П. Павлов). Речь изобилует сложными логическими построениями, вычурными абстрактными понятиями, терминами, нередко употребляемыми без понимания их истинного значения. Если больной с обстоятельностью стремится максимально полно ответить на вопрос врача, то для пациентов с резонёрством не важно, понял их собеседник или нет. Им интересен сам процесс мышления, а не конечная мысль. Мышление становится аморфным, лишенным чёткого содержания. Обсуждая простые бытовые вопросы, больные затрудняются точно сформулировать предмет разговора, выражаются витиевато, рассматривают проблемы с точки зрения наиболее абстрактных наук (философии, этики, космологии). Подобная склонность к пространным бесплодным философским рассуждениям часто сочетается с нелепыми абстрактными увлечениями (метафизической интоксикацией).

https://ru.wikipedia.org/wiki/Резонёрство

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

Вот теперь понятно, спасибо за разъяснения про работу set. Я то думал, что эти выражения должны быть эквивалентны. А так получается, что все логично.

bogus_result
()

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

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

Да, т.к. в Лиспе с fexpr'ами вообще нельзя сказать где код, а где данные до выполнения.

> (setq my-quote quote)
#<SPECIAL-OPERATOR QUOTE>
> (my-quote (a b c))
(a b c)

Можно пойти по одному из этих путей:

  • запретить fexpr'ы
  • забыть про компиляцию, статический анализ программ, статические IDE.

Первый путь плох тем, что непонятно почему мы запрещаем одну динамику, но разрешаем другую. Почему мы вообще предпочитаем языки высокого уровня, где грань в динамики, за которую нельзя заходить? Второй путь открывает огромные возможности метапрограммирования и дает пищу для осознания того, что поведение программы не вытекает непосредственно из ее текста. Последнее приводит к динамическим IDE (Squeak, например), которые построены вокруг REPL.

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

Второй путь открывает огромные возможности метапрограммирования

Наоборот. Фекспры строго менее выразительны чем макросы. Без строго разделения компайлтайма и рантайма метапрограммирования вообще просто нет.

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

Второй путь открывает огромные возможности метапрограммирования

Наоборот. Фекспры строго менее выразительны чем макросы. Без строго разделения компайлтайма и рантайма метапрограммирования вообще просто нет.

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

где грань в динамики, за которую нельзя заходить?

Всё зависит от конкретного случая, но компиляция нужна - это инструмент, который делает гигантский объём рутинной работы вместо тебя.

Я вот сейчас дорабатываю не очень большую (100-200кб) программу на старой версии Mathematica. Вот где полная динамика и полный ад. Всё можно:

- можно определить функцию с 4 аргументами, а вызвать с 5. Никакого предупреждения не будет выдано, ведь ты вправе вызвать функцию до того, как она определена, доопределять по ходу дела и у тебя есть ovelroad.

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

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

- всё лениво. Ленивость - это же крутая концепция программирования, зачем её запрещать? В итоге ошибки проявляются тоже лениво.

Так получаем 4 класса ошибок, с каждым из которых я плотно пообщался, потратив на это немало часов своего времени. Оказывается, свобода - это не всегда хорошо. Поэтому я постоянно наращиваю «иммунитет» в виде всяческих проверок. Не все проверки помогают из-за ленивости. Код проверок уже сопоставим по объёму с собственно кодом приложения. Вместе с этим уходит и гибкость, присущая системе Mathematica, и падает производительность программы, т.к. гибкий и некомпилируемый язык изначально медленный, а тут на него ещё навешивают проверки.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

- всё лениво.

Нет, не лениво

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

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

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

Там вообще нельзя определять ф-и. Только присваивать значение.

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

ф-и

Ого, anonimous ещё и специалист по «мощнейшим пакетам для символьных вычислений». Растёт.

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

Если считать, что (set 'x ...) и (setq x ...) одно и то же, то set обязан быть специальным оператором (как и setq).

Зачем? Это только в кривых лиспах, в нормальных set — обычная функция, setq — обычная ленивая функция.


(define (myset x y) (set x y))
(define-macro (mysetq x y) (set x y))

(let (a 1) (begin (myset 'a 2) (println a))) ;  2
(let (a 1) (begin (mysetq a 2) (println a))) ;  2

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

Точней вот так, сорри


(set 'b 2)

(define (myset x y) (set x y))
(define-macro (mysetq x y) (set x (eval y)))

(let (a 1) (begin (myset 'a b) (println a))) ;  2
(let (a 1) (begin (mysetq a b) (println a))) ;  2

//fixed

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

Это ты сейчас рассказал о своей полной некомпетентности, глупости, и беспомощности. Сочувствую.

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

Возможность переопределения функций, классов.

А что, есть языки где нельзя этого делать?

Интроспекция по отношению к объектам, классам, типам, ..

Языки поддерживающие интроспекцию: ... java ...

https://ru.wikipedia.org/wiki/Интроспекция_(программирование)

Это у нас и жаба теперь динамичная?

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

setq — обычная ленивая функция

Значит у тебя в твоём лиспе нет нормальных замыканий. Или как на нём сделать:

(defun make-adder ()
  (lambda (n)
    (lambda ()
      (incf n))))

(defvar *adder* (make-adder))
(defvar *a* (funcall *adder* 3))
(defvar *b* (funcall *adder* 33))

(funcall *a*) ; => 4
(funcall *a*) ; => 5
(funcall *b*) ; => 34
(funcall *a*) ; => 6

?

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

А что, есть языки где нельзя этого делать?

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

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от komputikisto

Очень мало программируют.
практическом отношении, то Lisp тебе не нужен.
питоном или руби.

Полная чушь. Сообщество лиспов небольшое, зато соотношение неадекватов/быдлокодеров много ниже, чем в том же питоне. Посмотри на Кложуру, сообщество растёт как на дрожжах, Интересных проектов вагон, Кложура портируется на дотнет, на питон, на руби, на перл, и даже на, о г-споди!

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

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

anonymous
()

Спрошу-ка здесь. Читаю On Lisp. Indeterminism — как это перевести (есть ли какой специальный термин?)

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

В каком контексте употреблялся термин? Это общефилософский термин. В википедии такое определение:

Индетерминизм — философское воззрение и методологическая позиция, отрицающие либо объективность причинной связи (онтологический индетерминизм), либо познавательную значимость причинного объяснения в науке (методологический индетерминизм).

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

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

Я ж сказал, это у Пола Грэма в On Lisp, Chapter 22-23 (?). Я хочу узнать у лисперов, может есть какой-либо более точный русскоязычный термин, которым можно перевести.

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