LINUX.ORG.RU

Вопрос про метаобъектный протокол.

 , ,


0

2

Я не могу никак взять в толк, что это такое.

Допустим, есть язык X и Y и в обоих есть метаобъекты. Но в X есть метаобъектный протокол, а в Y нет. Что будет такого, что можно сделать в X, но нельзя в Y?

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

Если не нравится new, то то же самое будет если просто обернуть в Object.

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

Да все правильно ты говоришь, я не спорю, что они неполноценные объекты, я сразу об этом и сказал, успокойся уже:)

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

Это — обёртки вокруг них, не они сами. Обёртки неявно добавляются на некоторых операциях, но далеко не на всех. Типичный boxing/unboxing.

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

можешь сделать что-то в таком вот роде

instance of 1 — это что? Отнаследоваться от fixnum в принципе могу

(defclass my-fixnum (fixnum)
  ((foo :accessor foo)
   (value :initarg :value :accessor value))
  (:metaclass from-builtin))

(defmethod my+ ((a fixnum) (b fixnum))
  (+ a b))

(defmethod my+ ((a my-fixnum) b)
  (+ (value a) b))

(defmethod my+ ((a fixnum) (b my-fixnum))
  (+ a (value b)))

(defvar one (make-instance 'my-fixnum :value 1)
(setf (foo one) "bar")
(my+ one 1) --> 2
(foo one) --> "bar"
(foo 1) --> error "no such slot"

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

Макрос — объект в борщелиспе

Да. Функция преобразующая список в список.

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

Не, на макросах там другая засыпка, макросы — не первокласные объекты языка, не в смысле ООП, а вообще, например, даже не обладают свойствами лямбда-выражений, примитивов, списков etc, это к ООП-объектам вообще не имеет отношения.

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

nstance of 1 — это что?

это экземпляр объекта 1

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

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

Есть понятие первоклассный объект языка. Его можно присвоить, подать в качестве аргумента, добавить в массив и так далее. Это понятие универсально для всех языков, вне зависимомти от поддержки ООП. Например, в хаскеле функция — это первоклассный объект.

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

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

В языках, где ООП на классах в принципе нельзя добавить слот уже существующему объекту (поэтому и появляется деление на объекты и классы/метаобъекты).

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

(setf (foo 1) "bbb")
(foo 1) -> "bbb"

Например, так

(let ((slot-one))
  (defmethod (setf foo) ((one (eql 1)) val)
    (setf slot-one val))

  (defmethod foo ((one (eql 1)))
    slot-one))

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

Есть какие-то другие объекты

Макрос можно применить к коду только в время компиляции. Поэтому он «не совсем объект».

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

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

При желании и макрос можно:

(defvar *loop* (macro-function 'loop))
(setf (aref array 0) *loop*)
...

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

В языках, где ООП на классах в принципе нельзя добавить слот уже существующему объекту (поэтому и появляется деление на объекты и классы/метаобъекты).

Ну, я не думаю, что это во всех языках с классовым ООП так.

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

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

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

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

Так передаю я не результат раскрытия, а сам макрос.

В чём разница между

* (car (list (symbol-function 'cdr) (symbol-function 'cons))) ;; функции

#<FUNCTION CDR>

и
(car (list (macro-function 'loop) (macro-function 'defun))) ;; макросы

#<FUNCTION (MACRO-FUNCTION LOOP) {10005B707B}>

?

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

Насколько я понимаю, разница в том, что во втором случае сначала раскроется macro-function 'loop и macro-function 'defun, и у тебя получиться (car (list tesult_of_macro-function_loop result_of_macro-function_defun)), и в итоге, уже в рантайме, tesult_of_macro-function_loop, а в первом, у тебя в рантайме выполниться сначала (symbol-function 'cdr) и (symbol-function 'cons) в итоге получиться result_of_symbol-function 'cdr, как то так. То есть, элементы листа выполняться в рантайме, в отличии от первого случая. Думаю так. Хотя я не спец по лиспу, хз. Но суть такая.

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

То есть, элементы листа выполняться в рантайме, в отличии от первого случая. Думаю так.

Нет. В обоих случаях всё выполнится в рантайме. macro-function — такая же обычная функция, как и symbol-function.

Магия макроса включается только при упоминании в коде. (car '(1 2 3)) вычислится в рантайме, а (loop for i from 1 to 10 collect i) сначала при компиляции выполнит (macro-function 'loop), применив её к '(for i from 1 to 10 collect i), а уже результат этого будет компилироваться.

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

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

у тебя в рантайме никаких макросов нет, там работает уже раскрытый код

Для CL это несовсем верно, там есть macro-function:

macro function n. a function of two arguments, a form and an environment, that implements macro expansion by producing a form to be evaluated in place of the original argument form.

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

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

не думаю, что это во всех языках с классовым ООП так

Вообще, если объекты одного «класса» могут иметь разные поля/методы, то это уже не классовое ООП, а прототипное. Хотя, может мимикрировать под классовое (JS ES6, Python)

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

Это — обёртки вокруг них, не они сами. Обёртки неявно добавляются на некоторых операциях, но далеко не на всех. Типичный boxing/unboxing.

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

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

Да ну нафиг объяснять семантику.

a = 1;
a.test = "passed: a";
console.log(a.test);
b = Object(1); // new Number(1)
b.test = "passed: b";
console.log(b.test);
console.log(a == b);
a — примитив, b — объект, instanceof Number. В этом вся разница между ними. b === boxed-версия a.

Это не деталь реализации, а вполне наблюдаемая разница в поведении.

И ещё уйма разницы выплывет если передать их как аргумент (by value vs by reference), да и не только.

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

Это не деталь реализации, а вполне наблюдаемая разница в поведении.

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

Если уж лезть в дебри, в JS вообще нет Ъ-объектов, поскольку в *настоящем* ООП, объект принимает сообщение, и сам решает, что с ним делать. Может проигнорировать, например, может вычислить переданные аргументы в своем контексте, может посмотреть, откуда сообщение пришло, может переслать его. Этого всего в JS нет, и накостылить так чтобы было органично, вряд ли получиться.

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

В этом соревновании могут участвовать только те, кто прошёл уровень с den73. (Я провалился)

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

Почему это не дают? Дают. a.test создаёт новый boxed-объект, кладёт в его test строку и выкидывает этот объект на милость garbage collector'у. А внутри a как был unboxed-примитив, так и остался.

В том же питоне числа/строки — Ъ-иммутабельные объекты, чьих родителей вплоть до type можно отследить. Ну и они выкидывают эксепшн при попытке сделать подобное. Тут же — ни родителей, ничего.

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

Дают

Ну да, дают, но эта возможность практически неюзабельна. Я сколько не пытался родить из этого хоть что-то полезное, ничего не вышло. поэтому, обо всех этих new String проще забыть.

Тут же — ни родителей, ничего.

Ну как, родители есть тем не менее. У new String родитель String, а у той, в свою очередь Object

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

В метапрограммировании — юзабельно. Что-нибудь может принимать любой кастуемый к String объект. Объект. Не примитив. НЕ ПРИМИТИВ STRING (разницу я уже раза 3 в этом треде показал). Тогда тебе понадобится new String или Object(), чтобы передать туда обычную строку.

Ну как, родители есть тем не менее. У new String родитель String, а у той, в свою очередь Object

А у обычной string — нет, поскольку это ни разу не объект.

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

разницу я уже раза 3 в этом треде показал

да я знаю разницу, я немного о другом говорил

В метапрограммировании — юзабельно. Что-нибудь может принимать любой кастуемый к String объект. Объект. Не примитив. НЕ ПРИМИТИВ STRING (разницу я уже раза 3 в этом треде показал). Тогда тебе понадобится new String или Object(), чтобы передать туда обычную строку.

Можешь показать пример? А то я не въехал что-то

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