LINUX.ORG.RU

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

Где тут противоречие?

противоречия нет, это просто факт.

Где проходит грань между CL и MOP?

Ну, она вполне очевидна. CL — это ядро языка, компилятор. А все остальное — надстройки, в виде модулей и тп, в тч и MOP. Это все равно что спросить в чем разница между JS и Nodejs

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

Кстати, в CL это и невозможно, собственно, чтобы любая сущность была консистентным типом, ведь сама объектная система CL — это надстройка над CL

Почему это невозможно? Я не вижу логики.

Это все равно что спросить в чем разница между JS и Nodejs

В браузере у меня нет NodeJS, а CL без MOP покажешь?

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

Метаобъектной системы и первоклассных функций в процедурном языке нет.

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

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

Почему это невозможно

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

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

метаобъектная система не относится к самому языку, в случае лиспа

Я готов поспорить что относится.

* (class-of 'x)	

#<BUILT-IN-CLASS COMMON-LISP:SYMBOL>
* (describe (class-of 'x))

#<BUILT-IN-CLASS COMMON-LISP:SYMBOL>
  [standard-object]

Slots with :INSTANCE allocation:
  %TYPE                        = (CLASS #<BUILT-IN-CLASS COMMON-LISP:SYMBOL>)
  SOURCE                       = NIL
  PLIST                        = NIL
  NAME                         = SYMBOL
  CLASS-EQ-SPECIALIZER         = #<SB-PCL::CLASS-EQ-SPECIALIZER {10012A6743}>
  DIRECT-SUPERCLASSES          = (#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>)
  DIRECT-SUBCLASSES            = (#<BUILT-IN-CLASS COMMON-LISP:NULL>)
  DIRECT-METHODS               = ((#<STANDARD-METHOD QL-DIST:SYSTEM-APROPOS-LIST (SYMBOL) {10055E63F3}>..
  %DOCUMENTATION               = NIL
  SAFE-P                       = NIL
  FINALIZED-P                  = T
  %CLASS-PRECEDENCE-LIST       = (#<BUILT-IN-CLASS COMMON-LISP:SYMBOL>..
  CPL-AVAILABLE-P              = T
  CAN-PRECEDE-LIST             = (#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>)
  INCOMPATIBLE-SUPERCLASS-LIST  = (#<STRUCTURE-CLASS COMMON-LISP:STRUCTURE-OBJECT>..
  WRAPPER                      = #<SB-KERNEL:LAYOUT for SYMBOL {10004BAF13}>
  PROTOTYPE                    = #:MU
loz ★★★★★
()
Последнее исправление: loz (всего исправлений: 1)
Ответ на: комментарий от loz

В браузере у меня нет NodeJS, а CL без MOP покажешь?

Тут такая же связь как между JS и DOM, мне кажется. JS — ядро, DOM — API. То что CL'овцы смешали это дефолтно, это скорей минус, чем плюс

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

Можно сделать

(defclass area2 (O2 H2O C) ())
(defclass area1 (H2O C) ())
В рантайме.

он же хотел его как defmethod объявить, а не как обычную функцию?

Суть defmethod в полиморфизме. Полиморфизма нет - смысла в defmethod нет, но да, можно заменить defun на defmethod, ничего не изменится.

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

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

is not alive because H19, C only exists.
H19

Молекулярный водород? :DDDDDDD

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

Суть defmethod в полиморфизме. Полиморфизма нет - смысла в defmethod нет,

Не знаю, как там в CL, но смысл не только и не столько в полиморфизме, сколько именно в проверке типов. Представь себе, что у тебя есть методы appendString и appendLine. Если у нас есть 2 объекта, и один из них имеет метод appendLine, который принимает на вход только тип Line, некий подтип строки, который не содержит в себе символов переноса строки, то если применить к нему appendString, вместо appendLine, то он это проглотит, но текст внутри него сломается, он добавит 2 или более строки вместо одной, в случае, если в качестве аргумента подана строка с переносами. И сделает это тихо. А поскольку в соответствующем объекте не реализован интерфейс appendString, он упадет с ошибкой в случае подобного вызова.

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

Где проходит грань между CL и MOP?

По спецформам. Они часть компилятора котрую нельзя вынести в библиотеки. MOP стандартизированя бибилиотека. Ее можно именно в силу текста стандарта считать частью языка, но по сути остается бибилиотекой => не частью именно языка. Лиспы годов 90-ых так и делали ее модулем.

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

Введение дополнительного типа в уже сформированную иерархию типов, когда она довольно сложна, - попаболь.

особенно в динамических языках

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

Метаобъектной системы

Если следовать первоисточнику Art of MOP то она спроектирована как реализация для процедурных языков. Для ООП или типизированого лямбда-исчисления вроде ML оно было бы ИМХО другим.

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

В Клипере например есть. Такие процедурные или мутировали в ООП или вымерли. Но для 90-ых ИМХО ситуация смешивания процедурщины с лямбдами как-раз характерна. CL заморозивший процесс стандартизации как-раз тогда - яркий пример. P.S. В Genera первокласные функции были CLOS-объектами.

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

а CL без MOP покажешь?

Можно даже найти где Pathname-ы иновация, не то что MOP. Но понятно что раритет:(

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

мне очень интересно стало почему это?

Потому что по определению работает при соблюдении особых условий = костыль. А ведь есть работы, где в качестве специализатора предполагалось использование произвольного предиката. Вот это не костыль.

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

Я не понимаю. Для меня основная фишка CLOS - комбинаторы методов - они позволяют повторно использовать код и адаптировать его под различные условия. Один из основных способов конфигурации комбинатора - отношения наследования между классами. Тебе ведь они нужны, если ты взялся использовать CLOS? Если да, то тогда как должен вести себя комбинатор, когда у тебя есть различные методы для разных пересекающихся множеств реализованных интерфейсов объекта?

method is-alive? ((area-object : (02 && h20 && c)))
method is-alive? ((area-object : (N2 && co2 && Zn)))
method is-alive? ((area-object : (O2 && Zn && c && N2)))
ados ★★★★★
()
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от no-such-file

эти «особые условия» есть стандартизованное и документированное поведение языка - в случае вызова call-next-method произойдёт дальнейшая диспетчеризация по менее специфичным методам, иначе диспетчеризация закончится на самом специализированном методе. В каком же месте это костыль?

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

Ну как и прописано в документации - должен выбираться самый специфичный метод. Случай когда несколько методов равно специфичны там также прописан, можно почитать. Но мне нужно кое что другое(понятное дело что этого я не получу). Мне нужно было сделать метод и прописать логику его выбора наперёд. Тогда можно создавать новые типы, не относя их к определённым группам, а проверять на принадлежность к этим группам с помощью уже реализованных методов. К примеру. Я могу пример придумать если не понятно, но надо ли?

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

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

type foobar_area1(derive: 02 Zn h20 c N2 co2)

is-alive? make(foobar_area1)

Какой из методов наиболее специфичный?

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

Мне нужно было сделать метод и прописать логику его выбора наперёд.

Вопрос будет надо ли штуке с такой логикой быть методом в разрезе CLOS. И вообще прописаная логика называется method-combination.

Просто для упоминания https://github.com/pcostanza/filtered-functions Но там статью или тесты надо смотреть для понимания вопроса.

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

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

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

Какой из методов наиболее специфичный?

если имеешь в виду описанные мной методы, то тот, в котором бОльшое число типов унаследовано, то есть:

method is-alive? ((area-object : (02 && h20 && c))):
    print "it's alive, all components here!"
я не понимаю, в чём ты нестыковку видишь?

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

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

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

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

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

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

И вообще прописаная логика называется method-combination.

разве оно для этого? Или в смысле можно реализовать такую логику с помощью method-combination, а потом получить портянку неподдерживаемого кода? Тогда уж лучше сделать руками совершенно другим механизмом, ну или создав свой defmethod2 с дополнительным механизмом диспетчеризации. Но вопрос не в том как это сделать. На самом деле вопрос уже исчерпал себя и тут уже просто спорят на тему а что если бы и как сделал бы каждый. На самом деле динамическая природа клиспа позволяет всё это сделать и на стандартном defmethod несколькими способами, но эти решения не очень обрадуют, когда попытаешься разобраться в них через некоторое время.

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

Насчет твоего вопроса - я помню где-то год назад слышал про эксперементальную поддержку либы для паттерн матчинга https://github.com/m2ym/optima в диспатчинге мультиметодов CLOS. Правда не помню в какой реализации и нагуглить не смог =(

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

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

xD

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

Я не эксперт по CL, чаще всего если я что-то пишу стараюсь по возможности избегать CLOS. Всякие MOP вообще в гробу видел. Может быть ты ещё сможешь выехать туда куда хочешь на библиотеках quicklisp, sbcl.

Тем не менее мне доводилось ломать голову над эффективным методом, который должен быть работать с двумя объектами из двух параллельных иерархий. У тебя интересная идея и как я понял ты хочешь чтобы её поддерживал CLOS. Мне кажется CLOS сильно прост для такого.

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

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

Не знаю как вы а я в лучшем случае ожидаю, что в тред войдёт эксперт CL 80 лвл, парочкой эффектных макросов с MOP магией заставит стандартный CLOS делать то что ты хочешь, а меня прямо или косвенно назовёт идиотом нихрена не смыслящим в CLOS.

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

А что я? Я не эксперт CL 80-го лвл. =)

Насколько я знаю, стандартными средствами CLOS это сделать нельзя (ну, кроме как наследованием ab <: a, b), а про filtered-functions уже упомянули. Я их не трогал.

korvin_ ★★★★★
()

Можно ли при объявлении defmethod указать, что у объекта должны быть наследованы несколько типов?

Кажется, можно - используя функцию compute-applicable-methods-using-classes (но только сам generic-method придется специализировать, так что не факт, что этот способ подойдет). Деталей не помню, к сожалению.

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

А чем отличаются типы от классов? Зачем это усложнение ввели?

У каждого объекта может быть только один основной класс (+ счётное число его предков) и несчётное число типов. Например, число 1. Класс у него integer. А типы — (integer 0 2), (integer -1 3), (integer -1 1),(satisfies oddp), ...

Классы в отличие от типов не могут пересекаться. Поэтому при наличии специализаций на двух классах для каждого объекта можно однозначно сказать какую вызвать. Если объект принадлежит обоим классам, значит один из них является потомком другого. Для типов это не так. (integer 0 3) и (integer -1 2) не являются потомками друг друга, а 1 входит в оба типа.

Поэтому, если делать ООП на типах, то придётся явно вводить приоритеты. Получится что-то вроде http://docs.racket-lang.org/gls/

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

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

нет! классы могут быть абсолютно независимы.

не, ну конечно, стандарт-класс будет для них общим предком.

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

нет! классы могут быть абсолютно независимы.

(defclass a () ())

(defclass b () ())

Что написать, чтобы создать объект, принадлежащий и a и b?

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

Что написать, чтобы создать объект, принадлежащий и a и b?

просто скопирую РЕПЛ

TEST> (defclass a () ((sa :initform :sa)))
#<STANDARD-CLASS TEST::A>

TEST> (defclass b () ((sb :initform :sb)))
#<STANDARD-CLASS TEST::B>

TEST> (defclass c (a b) ())
#<STANDARD-CLASS TEST::C>

TEST> (make-instance 'c)
#<C {1004567303}>

TEST> (with-slots (sa sb) * (list sa sb))
(:SA :SB)
anonymous
()
Ответ на: комментарий от anonymous

забыл уточнить.

при определении Ц, порядок перечисления А и Б важен! порядок используется методами для определения общности/специализации наследования.

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