LINUX.ORG.RU

Зачем нужны generic функции?

 , ,


1

6

Изучаю CL и вот наткнулся на них. Понял, что они последовательно по цепочки специфичности вызывают все аналогичные методы, но на кой черт это нужно и где может пригодиться не могу понять. Приведите пример пожалуйста.

★★★★★

они последовательно по цепочки специфичности вызывают все аналогичные методы

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

Begemoth ★★★★★
()

По-моему надо уточнить вопрос: зачем нужны комбинаторы методов.

Generic-функции для выполнения специфичного для класса кода - это вроде ясно из их аналогов в других языках.

ados ★★★★★
()

Контракт аргумументов для методов.

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

antares0 ★★★★
()

ну вот я пишу predict(model) и мне хорошо, поскольку тот кто написал model<-метод(data) уже озаботился написать predict.метод при написании library(метод). и работа разделена между писателями, и линия партии соблюдена. :)

PS как ни крути, а R это схема :)

psv1967 ★★★★★
()

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

А так, я использую для триггеров. Например, согласно шаблону .NET допустим, что объект имеет некоторое свойство. Есть событие, на которое можно подписаться, и которое уведомляет об изменении свойства. Еще есть триггер, который вызывает такое событие.

Так вот, триггер - это обобщенная функция. Внутренний обработчик триггера помещается в метод primary. Вызов самого события, помещается либо в метод :after, либо в метод :before в зависимости от типа события (changing / changed). Потом в потомках класса либо перекрывается метод primary, либо пишется метод :around.

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

Разумеется, это все автоматизировано с помощью макросов.

dave ★★★★★
()

но на кой черт это нужно и где может пригодиться

Перед изучением CL неплохо бы разобраться с основами ООП.

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

Зачем нужны generic

неплохо бы разобраться с основами ООП

С ООП в его классическом виде (C++/Python/Smalltalk/Ruby) дженерики очень слабо ассоциируются. Для ООП надо отправить объекту сообщение/вызвать метод объекта. Соответственно для каждой комбинации класс/метод тело объекта одно. И список методов/сообщения является интерфейсом класса и определяется вместе с ним также, как и поля.

В дженерике же при вызове может вызваться по четыре функции на каждый уровень иерархии по каждому аргументу. Кроме того, есть специализация по значениям параметров. Не будешь же ты считать (defmethod foo ((a (eql 7)) ) 42) «методом» числа 7?

То, что на дженериках удобно делать ООП не приравнивает их к ООП. А то можно и лямбды назвать ООП (на них тоже тривиально строятся поля и методы).

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

С ООП в его классическом виде (C++/Python/Smalltalk/Ruby)
C++/Python/Smalltalk/Ruby

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

Для ООП надо отправить объекту сообщение/вызвать метод объекта.

Терминология связанная с «отправкой сообщений» обычно используется в контексте Smalltalk и имеет больше исторического значения, чем практического смысла. Сейчас когда говорят о виртуальных функциях, то прежде всего говорят о диспетчеризации. И generic-функции являются совершенно естественным расширением диспетчеризации для несколько аргументов. Кроме того, известно множество попыток реализовать мультиметоды и для перечисленных языков, что только подтверждает естественность такого расширения.

А то можно и лямбды назвать ООП (на них тоже тривиально
строятся поля и методы).

Насчёт тривиально это, конечно, перебор, ибо в контексте CL это выливается в код, порождающий самые нехорошие чувства у читающих по отношению к автору. Вот в JavaScript, где есть удобный синтаксис для работы с lambda (и вообще функциями), вот там можно (но далеко не всегда нужно).

Но generic, в отличие от lambda, это часть CLOS и отрицать прямую связь между ООП и generic мне представляется невозможным.

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

Но generic, в отличие от lambda, это часть CLOS и отрицать прямую связь между ООП и generic мне представляется невозможным.

Раз уж затронули эту тему...

В лиспе все не так просто. Лямбды используются в CLOS, но по-другому. Да, я думаю, ты читал AMOP - видел у тебя в блоге один пример оттуда :)

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

Лямбды используются в CLOS

Так це ж не лямбды, а funcallable-объекты. Кстати, там какой-то совершенно несуразный API на эту тему.

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

Я имею в виду discriminating function и effective method functions, которые стоят за вызовом обобщенной функции. Это лямбды, а точнее замыкания. Когда вызывается обобщенная функция, то фактически вызывается лямбда. При первом вызове такая лямбда создается на лету.

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

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

Тут надо добавить, что лямбда для discriminating function достраивается на лету при каждом новом сочетании типов аргументов (плюс eql) - плата за динамический язык. В общем, внутри CLOS обычно используются лямбды (замыкания).

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

Я имею в виду discriminating function и effective method
functions, которые стоят за вызовом обобщенной функции.

make-method-lambda содержит в названии lambda, но должен возвращать не фактическую lambda, а s-выражение (содержащее описание lambda). Как реализация превращает это выражение в значения для set-funcallable-instance-function как бы личное дело реализации. Не факт, что там именно lambda.

Но это всё на самом деле не имеет никакого отношения к предмету обсуждения.

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

Нет, это другое. Это связано с тем, что происходит внутри CLOS при вызове обобщенной функции с заданными аргументами (см. compute-discriminating-function, compute-effective-method, compute-effective-method-function). Да взять к примеру первую упомянутую функцию из closer-clozure.lisp из системы closer-mop, хотя важнее, что находится внутри самой реализации лисп-машины. Closer-mop - это все таки оболочка.

Самая идея описана в AMOP в главе 4 «Protocol Design». И как я понял, многие реализации в основном придерживаются этого подхода с некоторыми вариациями (в книге не хватает eql, живого обновления и т.п.), и сам протокол оптимизирован по производительности.

А на ЛОРе начальная тема редко бывает интересной :)

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

Они просто называют compute-discriminating-function и compute-effective-method-function, а фактически имеют в виду лямбды не как s-expressions, а как реальные функции.

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

Нет, это другое.

Что другое? Это часть «Generic Function Invocation Protocol».

Я говорю о том, что сама спецификация протокола (http://www.alu.org/mop/concepts.html#generic-function-invocation-protocol) определяет только протокол, но не касается деталей того, как все эти эффективные методы и т.п. представляются внутри реализации. Про compute-discriminating-function сказано что она возвращает функцию. Во всём описании протокола lambda встречается только в методе make-method-lambda, но там это именно s-выражение.

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

Что другое? Это часть «Generic Function Invocation Protocol».

Другое в том смысле, что я писал о другом. Эту функцию приплел ты. Она тоже используется, но лямбда используется не только в ней.

Про compute-discriminating-function сказано что она возвращает функцию.

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

P.S. Это был риторический вопрос - ответа ждать не буду. Так, disclaimer на всякий случай, а то я тебя знаю :)

P.P.S. Андрей, если ты хочешь с кем-то поспорить просто так от нечего делать, то я тебе компанию составлять не буду. Я просто внес коррективы на счет недооценки использования лямбд в CLOS.

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

Я просто внес коррективы на счет недооценки использования
лямбд в CLOS.

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

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

С ООП в его классическом виде (C++/Python...

Кресты и пистон очень далеки от классики ООП. Так же как и Common Lisp. Классика ООП - это Simula (прото-ООП), Smalltalk (божественное воплощение ООП), Eiffel (вольное прочтение ООП), Object-C (недо-ООП на основе Си, но единственно-возможное ООП на Си). Из современных - Ruby (потомок smalltalk), Racket (неплохо реализованна библиотека для ООП), XOTcl (правильный вариант CLOSS), С++ и Python - только элементы парадигмы реализованы. Да и то коряво. Не вводи человека в заблуждение.

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