LINUX.ORG.RU

Доводы за раздельные неймспейсы для функций и переменных в CL

 , , ,


2

4

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

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

Не знаю, как в Clojure, но вроде они пошли по пути Scheme в этом плане.

Но вот есть некоторые сторонники Common Lisp, которые утверждают, что это все таки зло и котлеты отдельно, мухи отдельно.

Был бы рад подробной аргументации этого подхода, желательно в сравнении с подходом с общим пространством имен.

★★★

У этого подхода есть свои плюсы

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

no-such-file ★★★★★
()

Схема пытается быть функциональным языком. Это основной довод за.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от no-such-file

назвать переменную list - это эпик фейл

Переменная list - это список чего? Дописать через тире еще что это за список - вполне вариант(для параметра функции/макроса уж точно можно, а в остальных случаях и подавно).

Схема пытается быть функциональным языком.

Ским пытается, да. Но функциональная он примерно как и JS.

nihirash ★★★
() автор топика
Ответ на: комментарий от no-such-file

Назвать то можно, если осторожно. Да, можно потом ошибку огрести, но это случается не так часто.

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

list - это список чего?

Это список вообще. Для какого-нибудь find-what-i-want или list->my-blob

вполне вариант

Иногда не вариант.

для параметра функции/макроса уж точно можно

Как раз для макросов просто list гораздо естественнее.

Вообще идея lisp-2 в том, что символы суть слова, которые можно использовать как существительные и как глаголы. Т.е. run как переменная, и run как функция. ИМХО это просто мегафича.

no-such-file ★★★★★
()
Ответ на: комментарий от Virtuos86

. У лишперов новая ежегодная традиция?

Запоздалое осеннее обострение.

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

http://www.nhplace.com/kent/Papers/Technical-Issues.html

О) интересное чтиво.

В Похожих первая тема информативна. У лишперов новая ежегодная традиция?

Почитаю с удовольствием.

Вообще идея lisp-2 в том, что символы суть слова, которые можно использовать как существительные и как глаголы. Т.е. run как переменная, и run как функция. ИМХО это просто мегафича.

Возможно.

Прямо говоря, я писал в основном на picoLisp и Scheme.

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

На уровне «напилил бложик для собственного увеселения на localhost» профит не особо заметен, крупные системы пока не удавалось пилить на лисп-образных языках.

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

А что со схемой не так то?

По мне, с ней все отлично. Но ским все таки умеет(и это хорошо) в императивщину(и не только) с функциональной нечистотой.

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

Прикол в том, что и haskell прекрасно умеет в императивщину, но уже с функциональной чистотой

Отлично же!

nihirash ★★★
() автор топика
Ответ на: комментарий от no-such-file

Не иметь возможность в языке, основанном на списках, назвать переменную list - это эпик фейл.

А что мешает? Если не пытаться в этом же контексте делать новый список (вызывать функцию list), то проблем нет. А если пытаться, то на выбор a-list, lst, List в качестве имени переменной.

Зато не приходится всюду писать funcall и function.

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

До меня не доходит. :(

Потому что ты смотришь на лисп на язык программирования, а не как язык взаимодействия с лисп-системой в repl.

no-such-file ★★★★★
()
Ответ на: комментарий от monk

Зато не приходится всюду писать funcall и function

Ну и плохо что не приходится. В естественном языке мы всегда говорим либо «беги» (run ...), либо «используй бег» (funcall run ...).

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

У этого подхода только один плюс - проще в реализации

Практически идентично. Голову формы всё равно выделять надо, чтобы указатель на функцию получить и в этот момент в каком пространстве имён смотреть неважно. Разве что синтаксически. Приходится делать funcall, function, дублировать let/flet, let*/labels. И gensym для функций делать в макросах (почти) всегда забывают.

monk ★★★★★
()
Ответ на: комментарий от no-such-file

Как минимум нужно реализовать несколько слотов для символа.

Не обязательно. Например, к имени символа-функции добавляется префикс «f::».

monk ★★★★★
()
Ответ на: комментарий от no-such-file

Да. Действительно, проще поле в структуру добавить.

monk ★★★★★
()

Кстати, никто так и не сказал, как тут дела у кложи обстоят в этом плане.

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

Как у схемы

(defn make-adder [x]
  (let [y x]
    (fn [z] (+ y z))))
(def add2 (make-adder 2))
(add2 4)

А в CL придётся add2 или определять как (let ((add2 (make-adder 2)) (defun add2 (x) (funcall add2 x))) или всюду использовать через funcall. Оба варианта ужасны. Поэтому в CL функции, возвращающие другие функции (типа compose, curry и т.д.) плохо приживаются.

monk ★★★★★
()

Вот тебе задача, если нечем заняться:

;;; Problems:
;;;
;;; -- Constraint propagation badly interacts with bottom-up type
;;; inference. Consider
;;;
;;; (defun foo (n &aux (i 42))
;;;   (declare (optimize speed))
;;;   (declare (fixnum n)
;;;            #+nil (type (integer 0) i))
;;;   (tagbody
;;;      (setq i 0)
;;;    :loop
;;;      (when (>= i n) (go :exit))
;;;      (setq i (1+ i))
;;;      (go :loop)
;;;    :exit))
;;;
;;; In this case CP cannot even infer that I is of class INTEGER.
;;;
;;; -- In the above example if we place the check after SETQ, CP will
;;; fail to infer (< I FIXNUM): it does not understand that this
;;; constraint follows from (TYPEP I (INTEGER 0 0)).
А обсуждать твой вопрос уже несколько поздно.

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

Ну, согласен, без репла лисп бесполезен. Жутко удобно, надо что протестировать — послал выражение в репл и оценил ситуацию, что к чему. // Интересно, почему схемщики, ракетчики и кложурята не приняли концепцию разработки в образе как в CL.

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

Я так понял, если ты это запихнёшь в файл и сделаешь ему «compile and load», то высыпется куча замечаний (notes) о том, что он не смог оптимизировать. Но если ты раскомментируешь декларацию типа для i, то всё компилируется молча. Именно notes и показывают, что SBCL не может осознать наличие типа.

Но я не говорю, что это легко исправить.

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

В естественном языке мы всегда говорим ... «используй бег»

Это противоестественный язык.

Zmicier ★★★★★
()

Common Lisp не единственный Lisp-2. LFE тоже Lisp-2 и, по словам автора, причина в специфике Erlang VM.

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

Ским пытается, да. Но функциональная он примерно как и JS.

Ну никто ж не говорил что будет легко. Алсо, чего ты хочешь от языка из 70х, который представляет из себя творческую переработку языка из 50х?

hateyoufeel ★★★★★
()

Неймспейсов больше чем 2. Что классы? Почему тебя не смущает что они всегда в отдельном неймспейсе? И так далее

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

Да просто потому что сложно реализовать вот и все. Особенно у кложи, с жаба-рантаймом, нависающим над ней

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

Интересно, почему схемщики, ракетчики и кложурята не приняли концепцию разработки в образе как в CL.

Могу сказать про Racket. Потому что разработка в образе легко приводит к состояниям, которые трудно воспроизводимы из исходного кода. То есть если, скажем, неделю что-то пишешь без перезапуска образа, то потом, может оказаться, что при перезагрузке исходников с нуля программа не работает. И у тебя есть образ, в котором всё работает, но для которого нет исходников и исходники, которые надо как-то исправить, но неизвестно как.

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

То есть если, скажем, неделю что-то пишешь без перезапуска образа, то потом, может оказаться, что при перезагрузке исходников с нуля программа не работает. И у тебя есть образ, в котором всё работает, но для которого нет исходников и исходники, которые надо как-то исправить, но неизвестно как.

Проблемы высосанные из пальца.

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

Проблемы высосанные из пальца.

Разные подходы(я не считаю ни один из подходов хуже)

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

Интересно, почему схемщики,

всё у guile в порядке, особенно если редлайн подгрузить

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

а он что, код не хранит объявленной функции?

В запущенном образе? Нет.

А хоть один лисп так делает? В смысле, чтобы можно было получить исходник функции в образе?

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

В смысле, чтобы можно было получить исходник функции в образе?

Если этим озаботиться заранее, то нет проблем. Нужно переопределить defun в пакете так, чтобы он вызывал cl:defun и после этого записывал переданный исходник в plist символа.

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

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Нужно переопределить defun в пакете так, чтобы он вызывал cl:defun и после этого записывал переданный исходник в plist символа.

Ты же сам пишешь: (setf (symbol-function 'add2) (make-adder 2))

И толку тогда от переопределённого defun'а?

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

Воспроизводятся. Всё, что выполнено в образе можно записать в исходник и воспроизвести (это практикуется в Racket: там есть кнопка «сохранить историю REPL»).

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

Я на CL пытался разрабатывать в образе с помощью Emacs+SLIME. Пару раз из-за этого отправлял несобирающийся commit. То есть в образе через C-c C-c всё скомпилировал, протестировал, а через asdf ошибка. Потому что при тестировании руками через setf параметр поменял и забыл, а в исходнике не поправил. С тех пор у меня любимая команда в SLIME — restart-inferior-lisp.

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

И толку тогда от переопределённого defun'а?

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

Потому что при тестировании руками через setf параметр поменял и забыл

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

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

всё-таки не принято делать setf для функций

Я предлагал: (let ((add2 (make-adder 2)) (defun add2 (x) (funcall add2 x)))

В этом случае, конечно, у add2 будет исходник (funcall add2 x). Но толку от этого исходника всё равно не будет...

Впрочем setf и другие выражения, которые биндят функции тоже можно доопределить.

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

Что код зависит от окружения, а не просто набор функций.

Это окружение можно было и в исходник записать. Код на лиспе ведь тоже не просто набор функций.

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

можно пойти дальше, и озадачиться вопросом: как выводить не только простые типы, а и более сложные, наподобие размерностей или количественных физических моделей?

вот, к примеру интересный проект: How things work? и сопутствующая среда DME (развёрнуто)

это интересная сама по себе постановка задачи: машинно-генерируемые объяснения (физических моделей, патентов, изобретений)

допустим, у нас есть какая-то среда для представления знаний, и какой-то движок для вывода (на основе фреймовой сети, например, или тот же CLOS)

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

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

насчёт DME доступных исходников не нашёл, но рядом лежит курс по искусственному интеллекту от автора GLISP ещё (представление данных в GLISP — почти естественный английский язык)

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

любопытно, как в последнем исходнике или тут представляются знания, описывающие физческие законы

весьма наглядно: законы термодинамики

(defvar *physlaws*)
(setq *physlaws* '(
; Geometry
...
; Thermodynamics

; m = mass, dt = delta temperature, c = specific heat
(heat-transfer (m1 dt1 c1)
...
)
; heat = heat added to system
; work = work done by system
(thermo-system (initial-energy heat work)
  ((work-absorbed joule) (total-work joule) (energy-change joule)
   (final-energy joule) (initial-energy joule) (heat joule))
  ((= work-absorbed '(q 0 joule))  ; default
   (= total-work (- work work-absorbed))
   (= energy-change (- heat total-work))
   (= final-energy  (+ initial-energy energy-change))
))

(heat-engine (heat work)
  ((efficiency unity) (heat joule) (heat-exhausted joule))
  ((= work (- heat heat-exhausted))
   (= efficiency (/ work heat))
   (= max-efficiency (- 1 (/ temperature-cold temperature-hot)))
  ))
...
))

и прочая.

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

яр-модельяр

в общем, GLISP вполне себе интересный, дабы потыкать список файлов, составляющих GLISP

и попытаться запустить их под SBCL.

вообще, он был написан как IDE под XWindow древнее, и запускалка в комплекте работает через WeirdX, X сервер написанный на Java (и запускаемый везде, в том числе, и через браузер)

через браузер и через CGI работает и запускалка GLISP через GCL.

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

например, взять твой clcon + Яр с русским человекопонятным ЯП вместо лиспа аглицкаго басурманского, и по аналогии с онтологиями и представлением знаний в GLISP — описывать свои знания предметной области на понятном, наглядном, ограниченном русском упрощённом каком-то метаязыке (как сказал И. А. Ильин из статьи в защиту дореволюционной орфографии: «любая мысль на нашем языке выражена может быть, и любой другой язык выражать он можетъ, а вот сам он ни на одном заграничном языке выражен быть не может, во всей полноте своей» — сиречь, русский литературный по сути своей есть метаязыкъ)

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

и моделировать всякие двигатели Стирлинга и прочая на таком вот движке симуляции, с человекопонятным русским описанием (в том числе, и машинно-генерируемыемыми объяснениями).

невозбранно достигнувъ желаемого.

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