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 «аномалия», это что как если бы НЛО прилетело? Неужели Маккарти был настолько туп, что это казалось ему «аномалией»?



Последнее исправление: cetjs2 (всего исправлений: 3)

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

Кстати, насчёт динамических и лексических областей. Макросы тоже повлияли на выбор имеенно динамического подхода. Потому что так легче было делать. Достаточно посмотреть на syntax-case в Scheme, которые нужны для реализации Лисповых макросов с соблюдением лексических контекстов.

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

т.е., ILOS — облегчённый CLOS, а С++ — сильно упрощённый ILOS.

я к тому, что глобальные и локальные формы разделены.

то есть, время жизни defglobal/defdynamic — «глобальный» модуль, время жизни let/dynamic-let/flet — текущий модуль. с точностью до замыканий и продолжений, да.

минималистичное, модульное ядро CL никого не интересует.

ну есть например WCL, но кого и когда в CL интересовал минимализм и размер бинарников?

Abstract: Common Lisp implementations for Unix have traditionally provided a rich development environment at the expense of an inefficient delivery environment. The goal of WCL is to allow hundreds of Lisp applications to be realistically available at once, while allowing several of them to run concurrently. WCL accomplishes this by providing Common Lisp as a Unix shared library that can be linked with Lisp and C code to produce efficient applications. For example, the executable for a Lisp version of the canonical “Hello World!” program requires only 40k bytes under SunOS 4.1 for SPARC. WCL also supports a full development environment, including dynamic file loading and debugging. A modified version of GDB [1], the GNU Debugger, is used to debug WCL programs, providing support for mixed language debugging. The techniques used in WCL should also be applicable to other high-level languages that allow runtime mappings from names to objects.

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

Насчёт Лиспа без скобок — есть Dylan, такой себе Scheme с подмножеством CLOS, макросами и бесскобочным синтаксисом.

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

в обычном try-except-finally бывает finally, а в with-handler его не бывает.

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

это в стандарте CL есть зависящие от реализации require/provide, а в ISLISP их просто нет.

нет в стандартах, есть в реализациях. например, тот же OpenLisp.

> ага, только почему-то никто так не делает

ага, какие глупые коммонлисперы, ничего-то они не понимают.

всем пофиг. в коммерческих реализациях это всё есть, а концептуальная кривизна никого не волнует.

коммонлисперы тут берут пример с С++-ников-кактусоедов, чо.

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

ещё там есть D-выражения и свои AST-макросы с Skeleton Syntax Tree (как обобщение AST). совсем другая модель.

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

зачем оно, если дорогие реализации и так умеют выкидывать из конечного образа всё лишнее, и тот-же sbcl проще допилить до аналогичной фичи, нежели возиться с модульностью ядра?

ну вот взять kernel, или Shen / Kl.

одной и той же фичи можно добиться разными способами:

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

2. «ортогонализацией» используемых примитивов и концепций, как в Shen / Kl.

3. новыми концепциями, расширяющими старые — как в Kernel лисп-3, тау-выражения.

то есть, вообще говоря, нет такой задачи «минимизировать число спецформ вообще», есть задача «найти минимальное покрытие `языковых модулей` метаязыка концепциями-модулями языка реализации, которое позволяло бы делать всё то же самое, что и старым способом, только легче, понятнее, прозрачнее — на уровне концепций.»

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

то есть, есть концепция «объект»/«метакласс». эту концепцию можно реализовать в разных местах: в рантайме, в стд. библиотеке, доступной в компайл тайме, на урове «концепций метаязыка»

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

другое дело, если разумно закладывать сразу модульность. выделять новые сущности из языка реализации в метаязык, приписывать им семантику.

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

тогда для реализации технологии достаточно отмоделировать и затем реализовать метаязык стандарта, что может быть проще, чем исторически сложившаяся трудоёмкая реализация какого-то понимания устаревшей кодифицированной другой реализации (то есть, стандарта ad hoc, as is)

получить в итоге «более лучший лисп»

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

потому что например, в WCL был другой подход, более минималистичный и ИМХО, правильный. который напрямую интегрировался с С-миром. и простым обычным статическим Си-линкером.

вообще по идее, надо бы разделять систему на целевую и обеспечивающую — для обеспечивающей как раз имеет смысл полный функциональный CL, а вот целевую имеет смысл формулировать в более минималистичном виде, как С-систему или тот же ISLISP.

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

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

ок, любопытно проследить как развивались макросы — в лиспе на примере CL/ схема / что-то ещё лисповое (динамически?) и multi-staged meta programming в других языках (более статически?).

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

the executable for a Lisp version of the canonical “Hello World!” program requires only 40k bytes

просрали все полимеры, б*!

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

можно выкрутиться через RAII

это уже интересно. как можно выкрутиться через RAII?

нет в стандартах, есть в реализациях. например, тот же OpenLisp.

мало ли что там есть в OpenLisp-ShomepLisp, ты же расхваливал именно стандарт, вот цитата:

Или, язык ISLISP в частности (стандарт ISO и JEC) ... процесс стандартизации которых протекал более организованно, продуманно и рационально: тоже, в ISLISP ... нормальная модульность require/provide

придется тебе признать и эту ошибочку.

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

получить в итоге «более лучший лисп»

«сильно подозреваю», что в тех исторических условиях он бы «почил в бозе»

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

оттуда, что ты пишеь (yoba (x y z)) а не yoba(x y z) и не (yoba {y x z})

Не пусть я пишу (yoba {y x z}), несущественно.

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

Я ничерта не понял из этого арта. Давай ты перепишешь мой пример с when/yoba и покажешь.

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

и multi-staged meta programming в других языках (более статически?).

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

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

это уже интересно. как можно выкрутиться через RAII?

ну как в С++ выкручиваются с локами, например. в деструкторе пишем finally, чтобы удостовериться, что деструктор отработает, заворачиваем его в dynamic extent (dynamic-let).

придется тебе признать и эту ошибочку

cобственно, в стандарте языка ISLISP про модули вообще ничего нет. есть про ортогональные концепции, scope/extent/namespaces:

11 Scope and extent In describing ISLISP, the notions of scope and extent are useful. The first is a syntactic concept, the latter is a semantic concept. Although syntactic constructs, especially identifiers, are used to refer to runtime entities (i.e., objects arising during execution), a single entity cannot have both scope and extent. Scope is a feature of an identifier, referring to that textual part of an ISLISP text (see §4.38 and §5) within which this identifier occurs with unique meaning. Extent refers to the interval of execution time during which a certain object exists. A namespace is a mapping from identifiers to meanings. In ISLISP there are six namespaces: variable, dynamic variable, function, class, block, and tagbody tag. It is therefore possible for a single identifier to have any or all of these six meanings, depending on the context. For example, an identifier’s meaning is determined by the function namespace when the identifier appears in the operator position of a function application form, whereas the same identifier’s meaning is determined by the variable namespace if it appears in an argument position in the same form.

Complementary to scope which is a syntactic concepts, extent is a semantic concept: It describes the lifetime of entities. Objects are created at some time during execution. In most cases, it is undetermined when an object ends its existence: its lifetime begins when the object is created and ends when reference to it is no longer possible (and the object is subject to garbage collection). In this case the object is said to have indefinite extent. In other cases the processor creates entities that are associated with prepared text. The lifetime of such objects begins at the activation point of a defining construct and ends at the end of activation; in this case the object is said to have dynamic extent.

собственно, стандарт на язык ISLISP и не должен это описывать, потому что это implementation-specific.

в терминах стандарта, ISLISP processor это реализация компилятора/интерпретатора.

вот стандарты по ISLISP processor, то есть, реализациям — тоже описаны:

Nobuto Izumi and Takayasu Ito. A Package System for an ISLISP Processor TISL. [In Japanese] Information Processing Society of Japan Transactions on Programming, Volume 40, Number SIG10, December 1999. PDF at ci.nii.ac.jpAlso presented at Japan Lisp User Group Meeting, May 18-19, 2000. PDF at franz.com

например, в OpenLisp-шмопенлисп возможно такое:

(in-package "foobar")
(export '("fubar" "baz" "xyzzy" "snafu" "") "foobar"
(require "setf")
(require "loop")
....
(provide "yoba")

здесь есть и пакеты в стиле CL, и require/provide модули в стиле схемки.

в итоге, все эти 40 спец. форм можно выразить макросами. этому способствует описание scope/extent/namespaces в стандарте, и модули в реализации.

но да, модульность зависит от реализации — стандарте на ISLISP processor, а не на ISLISP язык, признаю.

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

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

спорно. вот AST-макросы, где нужно колбасить вручную — это макросы или нет? в какой момент статика с многостадийностью становится динамикой с макросами?

с точки зрения результата-то всё равно как его получать.

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

чтобы удостовериться, что деструктор отработает, заворачиваем его в dynamic extent (dynamic-let).

прекрасно.

ладно, допустим в ISLISP есть деструкторы (хотя их там и нет, конечно). расскажи, как завернуть деструктор в dynamic extent. в ISLISP, про C++ не надо.

cобственно, в стандарте языка ISLISP про модули вообще ничего нет. есть про ортогональные концепции, scope/extent/namespaces:

надеюсь, ты прочитал скопированную тобою простыню и убедился, что эти scope/extent/namespaces никакого отношения к модулям тоже не имеют.

признаю

хорошо, что признаешь.

и не стыдно тебе, анонимус? безапелляционно сообщил целую кучу вызывающе неверных фактов о стандарте ISLISP, только в том, что setq без defdynamic вызывает ошибку, не наврал; показал, что тебе лень ознакомиться даже со 134-страничным документом, и при этом еще позволяешь себе иметь мнение о 1050-страничном. как же так? пора тебе совесть заиметь.

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

в какой момент статика с многостадийностью становится динамикой с макросами?

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

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

с точки зрения результата-то всё равно как его получать.

И в какой момент императивное программирование становится функциональным?

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

питон какой то получается :)

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

примерно в такой, когда в язычке типа D появляются транзитивный immutable и pure модификатор для функции.

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

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

расскажи, как завернуть деструктор в dynamic extent. в ISLISP, про C++ не надо.

да примерно также, как и в CL: CL-RAII

тоже самое, деструкторов нет — а RAII можно сделать.

(in-package :cl-raii)
(defgeneric finalize (object)
  (:documentation "The generic finalizer which everyone has to implement."))

(defmethod finalize (object)
  "The general case for objects. Just a do-nothing."
  (values))

(defmethod finalize ((object stream))
  "Finalizer for streams, which includes files."
  (close object))

(defun ensure-car (x)
  "Get the CAR of x if it has one, otherwise just return the object itself."
  (if (consp x) (car x) x))


(defmacro with ((&rest bindings) &body body)
  "The RAII-like WITH macro. Automatically finalize objects declared
in BINDINGS with its corresponding FINALIZE method."
  (let ((cars (mapcar #'ensure-car bindings)))
    `(let ,bindings
       (unwind-protect
            (progn ,@body)
         ,@(loop
              :for sym :in cars
              :collect `(cl-raii:finalize ,sym) )))))

(with)

usage:

(with ((o obj)) (foobar o))

example:

(defclass foo () (x :accessor foo-x :initarg _x) )
(defmethod finalize ((object foo)) (format t "FUBAR SNAFUed") )
(with ((f (make-instance 'foo '_x 444) )) (format t "QWE" f) )

;(macroexpand '(with ((f (make-instance 'foo '_x 444) )) (format t "QWE" f) ))
; =>
; (LET ((F (MAKE-INSTANCE 'FOO '|_X| 444))) (UNWIND-PROTECT (PROGN (FORMAT T "QWE" F)) (FINALIZE F)))

(with ((s (make-instance 'stream))) foobar) 
; s закроется в (defmethod finalize ((object stream))
anonymous
()
Ответ на: комментарий от anonymous

только здесь в ISLISP вместо let будет dynamic-let, вместо loop (нет в стандарте ISLISP, есть модулем макросами в OpenLisp) будет for цикл.

(require "loop")
(defmacro dyna-with ((&rest bindings) &body body)
  "The RAII-like WITH macro. Automatically finalize objects declared
in BINDINGS with its corresponding FINALIZE method."
  (dynamic-let ((cars (mapcar #'ensure-car bindings)))
    `(dynamic-let ,bindings
       (unwind-protect
            (progn ,@body)
         ,@(loop
              :for sym :in cars
              :collect `(il-raii:finalize  (dynamic ,sym) ))))))

здесь не забивается лексическая область видимости, а используется динамическая (соотв., внутри dyna-with будет не (foobar o), а (foobar (dynamic o)) ).

The dynamic value associated with such an identifier is the one that was established by the most recently executed active block that established it, where an active block is one that has been established and not yet disestablished. Because a separate mechanism is used, the lexical meaning of and the dynamic value associated with an identifier are simultaneously accessible wherever both are defined.

то есть, активный блок устанавливает try, по окончанию активного блока макрос через unwind-protect собирает finally и вызывает их вручную.

1. другое дело, что при unwind-protect (и в CL, и в ISLISP) в объекты заворачивать и не надо — хватит unwind-protect.

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

2. а по большому счёту, такой макрос with не так уж сильно нужен в ISLISP, потому что весь этот with это по сути эмуляция dynamic-let (только завёрнутая в unwind-protect), и если на уровне соглашений рантайма это обыграть — не нужно вызывать вручную, — финализатор вызовется автоматически (если он предсказуемо вызывается рантаймом в один и тот же момент, закрытия активного блока), и перекрывая «деструктор»-финализатор реализуем там finally ветку исключения.

CL:

(with ((s (make-instance 'stream))) foobar) 
; s закроется в (defmethod finalize ((object stream))

эквивалентно (dynamic-let ((s (create <stream> 'filename «foo.txt»)) foobar))

-- в ISLISP dynamic-let это отдельное пространство имён, в CL общее — поэтому нужен макрос, чтобы собрать привязки, завернуть, и финализировать.

и уже есть (with-open-output-file (outstream «example.dat») foobar), with-output-stream, with-input-stream, with-string-input-stream и т.п. в спец. формах, которые всё это делают для потоков.

для произвольных объектов по идее и unwind-protect не нужен — если как-то на уровне рантайма договориться, что деструкторы называются finalize и если есть, то они вызываются. ЕМНИП по дефолту это не так.

ещё можно из Lisp-6 ISLISP сделать LISP-7 для try-except-finally, или отдельно для RAII (если расширить понятие «активный блок» с динамических переменных на соотв. исключения или объекты), но это уже спец. олимпиада: ведь есть в ISLISP и unwind-protect, и catch/throw, и условия(сигналы) и перезапуски, и with-handler для условий и перезапусков (handler-bind в CL). так что нормальный ответ был бы: «реализовать finally через рестарты».

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

надеюсь, ты прочитал скопированную тобою простыню и убедился, что эти scope/extent/namespaces никакого отношения к модулям тоже не имеют.

модуль — это концепция, соединяющая на своём уровне связи между символами/идентификаторами и scope/extent/namespaces в одну сущность.

где и как они реализованы — не важно. на уровне рантайма реализации, или на уровне макросов.

в CL пакет это сущность на уровне стандарта и рантайма, в ISLISP тоже полагаются на рантайм, но на уровне реализации. а можно сделать и на уровне макросов (опять делаем из LISP-6 LISP-7 или LISP-8).

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

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

не лень. ознакомился. и позабыл благополучно. так что что-то мог и напутать: что-то отложилось от стандарта, что-то — от реализации, которая, потыкав — показалась проще, понятнее и легче, чем общелисп.

но, факт остаётся фактом: чем меньше букв в стандарте, тем он понятнее, непротиворечивее, и удобнее и эффективнее для реализации.

и это не только моё мнение, это факт. если одно и то же можно описать кратко, а можно — многобуквием — то зачем платить больше?

anonymous
()

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

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

в ISLISP вон для этого выделили отдельные пространства имён для лексических, и отдельные — для динамических, чтобы а) не путать б) пользоваться обоими одновременно. Фича б) странная, но иногда может пригодиться.

но они и на этом не остановились: сделали Lisp-6: переменные, динамические переменные, функции, классы, блоки, tagbody. в итоге один и тот же идентификатор может иметь 1..6 смыслов в разных контекстах.

для тех, кому и этого мало: есть возможность расширения набора спец. форм в зависимости от реализации.

каждая спец. форма имеет блок активации, область видимости и т.п., спец. операторы (по которым различается N в Lisp-N)

например, можно было бы на уровне синтаксиса добавить к S-expressions С-expr, N-exprs, t-exprs в виде Lisp-{7,8,9}, как отдельные спец. формы, и вычислять из этих 7-8-9 обычные S-exprs для Lisp-1,2(..6)

здесь на уровне стандарта уже ясно, что разные классы форм — в разном N, в разных пространствах имён.

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

потому что с точки зрения Lisp-2 это и есть аномалия: одно пространство «переменных» для лексических и динамических, и порядок не определён.

с точки зрения Lisp-3 c пространствами «переменные, динамические переменные, функции» это обычное дело. или с точки зрения ISLISP (Lisp-6) — тоже.

с точки зрения какого-нибудь естественного языка (ЕЯ) с пространствами Verb-Subject-Object здесь Lisp-3 как минимум, норма жизни. но для разных других частей речи (наречие, деепричастный оборот, герундии и т.п.) 3 тоже может быть маловато, то есть все эти 3 разных классов и метаклассов.

с точки зрения Схемы, Lisp-N где N>1 уже само по себе аномалия. они пытаются «ортогонализировать» эти сущности в одно общее пространство имён, что, ИМХО fail.

вообще вот нормальный пример: естественный язык с Lisp-N или схемка с Lisp-1.

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

с точки зрения Схемы, Lisp-N где N>1 уже само по себе аномалия.

Схема это Lisp-алеф-нуль, если ты не знал.

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

ты вот не считай все эти алефы и прочие бет омега  — для этого нумератор какой-никакой нужон. а сразу пальцем ткни, как в массив — вот они, Lisp-N, все N сразу под рукой, у каждого понятный «физический смысл».

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

через монады же. монада это нумератор этих алефов.

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

ты вот не считай все эти алефы и прочие бет омега — для этого нумератор какой-никакой нужон. а сразу пальцем ткни, как в массив — вот они, Lisp-N, все N сразу под рукой, у каждого понятный «физический смысл».

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

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

а если вдруг потребуется вертеть объектами из разных фаз одновременно, чо делать? как например, в ISLISP с лексическими (x) и динамическими (dynamic x) переменными?

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

нумератор алефов, ага.

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

как например, в ISLISP с лексическими (x) и динамическими (dynamic x) переменными?

Чего?

Вообще все эти неймспейсы для ф-й/переменных/етц тривиально реализуются в виде макробиблиотеки.

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

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

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

Любой макрос работает как минимум с двумя фазами.

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

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

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

реализовать finally через рестарты

ответ неправильный

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

что-то отложилось от стандарта, что-то — от реализации

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

и это не только моё мнение, это факт

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

anonymous
()

про кластер метапарадигм

существует классическое понимание, что такое N в Lisp-N. например: схема это лисп-1, потому что пространство имён одно, для переменных (просто некоторые переменные функционального типа). общелисп это лисп-2, потому что для переменных и для функций два разных пространства имён. в смысле этого понимания, ISLISP это лисп-2, также как и общелисп.

с другой стороны, с альтернативного понимания, ИМХО, ISLISP можно считать и лисп-6. потому что прямо в стандарте определено, что в ISLISP существуют 6 пространств имён: переменных, динамических переменных, функций, классов, блоков и tagbody (меток).

рассмотрим некоторый сферический в вакууме метаязык металисп лисп-N. какие N могут быть полезны, и как какой «физический смысл» у такой башни метаязыков?

лисп-0: нетипизированное лямбда исчисление. «общее пространство имён»

лисп-1: схема. спец. формы let переводят содержимое из пространства имён переменных в «общее пространство имён». спец. форма для функций — не нужна, т.к. функция это или переменная может хранится в списке свойств символа, т.е., глядя на символ, однозначно понятно, как его вычислять. макросы реализуются как функции над синтаксическими объектами, сферическими и в datum, во время отдельной фазы. гигиена есть, что позволяет делать модули.

лисп-2: общелисп. два отдельных пространств имён для переменных и для функций, отсюда необходимость в спец. форме function (сахар #'*) и apply. спец. формы переводят контент из отдельных пространств имён в общее. спецформ много, целых 25 на все случаи жизни. список спецформ не расширяемый, только эти 25, не больше и не меньше. макросы реализуются как подстановка над quote/unquote/comma. гигиены нет, зато есть gensym. модулей нет, есть пакеты.

кроме того, есть неоднозначность с переменными: если динамическая «затеняет» лексическую, какая должна быть использована? неоднозначность возникает из-за того, что пространство имён для переменных — одно.

лисп-3: ??? что бы это могло быть?

например, есть kernel — лисп, в котором макросы реализованы через fexpr. такая модель называется тау-выражения. идея в том, что если в «классических лиспах» и макросы, и функции работают с тем же самым окружением в eval/apply, то здесь можно использовать разные окружения. соответственно, вычисление макросов — это вычисление таких разных окружений.

назовём такой лисп лисп-3: переменные, функции и макросы.

лисп-4, лисп-5: НЁХ. интересно, что бы это могло быть?

лисп-6: ISLISP в альтернативном пониманиии выше. 6 пространств имён: переменных, динамических переменных, функций, классов, блоков и tagbody (меток).

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

если пространств переменных два — неоднозначность с переменными убирается. в лексическом — как обычно, в динамическом — нужны спец. формы defdynamic/dynamic-let для объявления глобального/локального и dynamic для обращения из третьего пространства имён в общее.

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

состав спец. форм — расширяемый, зависит от реализации — в отличие от общелиспа.

anonymous
()
Ответ на: про кластер метапарадигм от anonymous

про кластер метапарадигм (сontinued).

далее, продолжаем банкет.

лисп-7: макросы как в kernel и тау-выражениях.

лисп-8: модули. лисп-9: НЁХ: концепты, аспекты, субъекты в соотв. концептно-,аспектно-,субъектно- ориентированном программировании.

хотя не, как-то это недостаточно концептуально. парадигмы, вот! (мы же про кластер метапарадигм, правильно?)

лисп-10: спец. формы. (если в ISLISP состав спец. форм зависит от реализации, почему бы не пойти дальше — сделать состав спец. форм зависимым от самой программы?)

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

лисп-10500 не нужен, т.к. новые сущности не выдумываются.

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

лисп-11: типы. и соотв., типизированное лямбда-исчисление вместо лисп-0. спец. формы теперь переводят в другое общее пространство имён: лисп-11 вместо лисп-0. можно сочинить транслятор из лисп-11 в лисп-0, для общности (хотя интереснее лисп-0 с аннотациями в лисп-11).

сбылась мечта идиота — типизированный лисп.

лисп-12: монады, куда же без них (следующий логичный шаг после типов).

зигохистоморфные препроморфизмы это спец. формы, отображающие лисп-12 в лисп-11 (или любой другой лисп-k, k=1..10) — «нумераторы сущностей с мощностью алеф ноль»

монады монад это нумераторы нумераторов и т.п.

лисп-13: всё, приплыли. кажется, кластер метапарадигм построен.

при этом и лисп-11,лисп-12 по большому счёту, не нужны, достаточно лисп-10.

(впрочем, с точки зрения минимализма кому-то достаточно и лисп-1 или лисп-алеф0.

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

ты не умничай, ты пальцем ткни — сразу попадёшь в какое-то пространство имён)

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

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

строго говоря: ясно, что классы и объекты, например, можно реализовать на замыканиях или на макросах (то есть, 4 пространство не ортогонально первым двум или 7-му)

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

например, можно реализовать 4 пространство через первые два или 7-е или те же блоки и tagbody (5,6). или замыкания через 5,6. а потом сравнить, чья реализация прямее.

вот, он какой, кластер метапарадигм в металиспе лисп-N.

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

я, например, придерживаюсь другого мнения.

то есть, считаешь, что сложный и громоздкий стандарт лучше чем краткий, простой и понятный?

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

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

в лиспе у всех объектов неограниченное время жизни.

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

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

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

Это не мешает сделать объект с двумя состояниями: «Владеет ресурсом», «Не владеет ресурсом», и необратимым переходом из одного в другое.

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

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

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