Re[2]: Насколько необходима множ. диспетчеризация?
От: Кодт Россия  
Дата: 01.03.06 23:19
Оценка: 35 (4) +1
Здравствуйте, VladD2, Вы писали:

VD>Так как 99% языков без них обходятся, то и говорить не о чем. К тому же как я понимаю, фишки языка вроде сопоставления с образцом могут очень достойно заменять мультиметоды. Вот простенький пример на Нэмерле:


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

Особенность мультиметодов — в том, что, если не определены все возможные комбинации типов, то возникает неоднозначность, по какой ветке пойти в случае неточного совпадения.
Эту неоднозначность разрешают разными способами.
Самые распространённые
— порядок, определённый пользователем (таблица сопоставления с образцами, собранная вручную)
— лексикографический порядок (двойная диспетчеризация; автоматически заполненная таблица)

На ёлку влезть и рыбку съесть — не получается. Либо мы вводим устраивающий нас порядок и платим за это плохой масштабируемостью и сопровождаемостью (попробуйте отладить таблицу сопоставления, если в иерархиях по 50 классов). Либо подстраиваемся под жёстко прибитый порядок, получая внятную логику и возможность масштабирования.

А фишки языка... они большого значения не имеют. Проблема-то именно архитектурная.

Даже в С++ можем нагородить if(dynamic_cast<X*>(a) && dynamic_cast<Y*>(b))... или что-нибудь подобное. Ну там макросами оформить. В конце концов, MFC строит таблицы виндовских сообщений (кстати, тоже вариация на тему мультиметодов) макросами, и все счастливы.
Перекуём баги на фичи!
Re: Насколько необходима множ. диспетчеризация?
От: Дарней Россия  
Дата: 28.02.06 22:19
Оценка: +4
Здравствуйте, Курилка, Вы писали:

К>Собственно сабж.

К>Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.

они позволяют, например, избавляться от уродливых конструкций вида
if (x is TypeA)
{
....
}
else if (x is TypeB)
{
....
}
....

визиторы, кстати, это один из частных случаев мультиметодов — по своей сути эмуляция двойной диспетчеризации
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[3]: Насколько необходима множ. диспетчеризация?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.03.06 21:57
Оценка: +3
Здравствуйте, Курилка, Вы писали:

К>А теперь к моему вопросу — насколько это востребованно?


Все зависит от задачи.

Например, если задача "распознать" дерево, то можно:
1. Восспользоваться ООП и паттерном Посетитель.
2. Воспользоваться сопоставлением с образцом.
3. Воспользоваться мултиметодами.

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

Использвать же "if (x is Y)" в ОО-языках крайне не удобно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Насколько необходима множ. диспетчеризация?
От: Кодт Россия  
Дата: 03.03.06 13:06
Оценка: +3
> C>Ага. Классическая двойная диспетчеризация — по типу аргумента (коду
> C>сообщения) и по указателю 'this'.
>
> Хм. Но сообщение является целочисленной константой. То есть второй параметр не полиморфен. Так что это обычный вызов.

Это всё-таки полиморфный вызов с вариантным аргументом. Ну а то, что это всё реализовано на единственной точке входа и целочисленных параметрах — ну так винапи это же, считай, ассемблер.
Posted via RSDN NNTP Server 2.0
Перекуём баги на фичи!
Re[5]: Насколько необходима множ. диспетчеризация?
От: remark Россия http://www.1024cores.net/
Дата: 22.04.06 22:14
Оценка: 6 (1)
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, remark, Вы писали:


R>>Не согласен. Визитор просто позволяет вынести виртуальный метод из иерархии классов в один отдельный класс.


AVK> Мы точно под визитором одно и том же понимаем?


GOF?


R>>Нет, его конечно можно назвать мультиметодом для объектов (тип действия, класс),


AVK>Мультиметод чистейшей воды, просто реализация несколько неуклюжа.


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



R>> но это называется просто методом. Диспетчерезацию по типу метода всегда выполняет сам программист, когда после точки пишет имя метода.


AVK>В классической реализации визитора имя метода Visit всегда одно и то же, а диспетчеризацию выполняет компилятор за счет перегрузки этого метода по типу возвращаемого значения.


Сейчас попробую объяснить, что я имею в виду.
Как обычно используется визитор:
IShape s = new Circle();
IVisitor v = new DrawShapeVisitor();
s->visit(v);


Что мы тут имеем? "Существительное" — фигура (IShape). "Сказуемое" — нарисовать (DrawShapeVisitor). Т.е. существует всего одно существительное, а не два (и не три). Для мультиметода надо хотя бы два существительных! Например:
IShape s1 = new Circle();
IShape s2 = new Square();
DrawInterseptionMultimethod(sq, s2);


Вот это мультиметод. Согласен. Существительных два. + есть ещё и действие — собственно мультиметодв.

А в первом случае. Есть только одно существительное и действие.
Сравним первый пример с таким:
IShape s = new Circle();
s->DrawShape();


Чем отличается? Кроме организации кода — ничем.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Насколько необходима множ. диспетчеризация?
От: Oyster Украина https://github.com/devoyster
Дата: 27.02.06 09:07
Оценка: 1 (1)
Здравствуйте, Курилка, Вы писали:

К>Вопрос не в том, есть ли применение вообще, а скорее насколько такие задачи часто встречаются


Имхо всё зависит от конкретного проекта — у меня вот ни разу не было необходимости. В общем, если её нет, то можно сэмулировать средствами языка (как правило) или реализовать по другому, если есть — нехай будет

С другой стороны, возможно, я просто не умею её готовить и поэтому не использую, хотя мог бы.
Re: Насколько необходима множ. диспетчеризация?
От: Oyster Украина https://github.com/devoyster
Дата: 27.02.06 08:56
Оценка: +1
Здравствуйте, Курилка, Вы писали:

Представь себе, что у тебя есть набор примитивных объектов, над которыми надо делать, например, операцию сложения. При этом объекты разного типа можно складывать, но правила сложения разные. Например, есть у тебя .NET BCL и в ней есть int, double, DateTime, TimeSpan, которые все между собой замечательно складываются (int + double => double, int + DateTime => DateTime, double + TimeSpan => TimeSpan). Писать такой метод сложения без мультиметодов напряжно — приходится их "реализовывать" через reflection и хеш-таблицы.

Привёл такой пример потому, что в форуме dotnet он пробегал как часть реального проекта.

В общем-то, всему найдётся реальное применение, просто иногда с ходу тяжело его назвать, если сам не сталкивался.
Re[3]: Насколько необходима множ. диспетчеризация?
От: remark Россия http://www.1024cores.net/
Дата: 08.03.06 01:37
Оценка: -1
Здравствуйте, Курилка, Вы писали:

Д>>визиторы, кстати, это один из частных случаев мультиметодов — по своей сути эмуляция двойной диспетчеризации


К>Не спорю



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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Насколько необходима множ. диспетчеризация?
От: Курилка Россия http://kirya.narod.ru/
Дата: 27.02.06 08:41
Оценка:
Собственно сабж.
Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.
Re: Насколько необходима множ. диспетчеризация?
От: PoM-PoM 40mm Россия  
Дата: 27.02.06 08:50
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Собственно сабж.

К>Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.

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

У меня был лично еще такой пример — делал очередь операций (Undo/Redo), так вот — некоторые операции — например перемещение объекта, было бе не плохо склеить в одну (потеряв информацию промежуточном состоянии за ненадобностью) и сэкономить памят и все такое. Жутко интерсено узнавать можно ли склеить 2 операции и что получиться в результате. классов операций было около 50 так что скучно все без ММ
Will give me piece of mind
Re[2]: Насколько необходима множ. диспетчеризация?
От: Курилка Россия http://kirya.narod.ru/
Дата: 27.02.06 09:02
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Здравствуйте, Курилка, Вы писали:


O>Представь себе, что у тебя есть набор примитивных объектов, над которыми надо делать, например, операцию сложения. При этом объекты разного типа можно складывать, но правила сложения разные. Например, есть у тебя .NET BCL и в ней есть int, double, DateTime, TimeSpan, которые все между собой замечательно складываются (int + double => double, int + DateTime => DateTime, double + TimeSpan => TimeSpan). Писать такой метод сложения без мультиметодов напряжно — приходится их "реализовывать" через reflection и хеш-таблицы.


O>Привёл такой пример потому, что в форуме dotnet он пробегал как часть реального проекта.


O>В общем-то, всему найдётся реальное применение, просто иногда с ходу тяжело его назвать, если сам не сталкивался.


Вопрос не в том, есть ли применение вообще, а скорее насколько такие задачи часто встречаются
Re[2]: Насколько необходима множ. диспетчеризация?
От: Курилка Россия http://kirya.narod.ru/
Дата: 01.03.06 09:36
Оценка:
Здравствуйте, Дарней, Вы писали:

Д>они позволяют, например, избавляться от уродливых конструкций вида

Д>
Д>if (x is TypeA)
Д>{
Д>....
Д>}
Д>else if (x is TypeB)
Д>{
Д>....
Д>}
Д>....
Д>


А теперь к моему вопросу — насколько это востребованно?

Д>визиторы, кстати, это один из частных случаев мультиметодов — по своей сути эмуляция двойной диспетчеризации


Не спорю
Re[3]: Насколько необходима множ. диспетчеризация?
От: Дарней Россия  
Дата: 01.03.06 09:43
Оценка:
Здравствуйте, Курилка, Вы писали:

К>А теперь к моему вопросу — насколько это востребованно?


мне этого часто не хватает. Насчет остальных не знаю
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[3]: Насколько необходима множ. диспетчеризация?
От: Дарней Россия  
Дата: 01.03.06 10:58
Оценка:
Здравствуйте, Курилка, Вы писали:

К>А теперь к моему вопросу — насколько это востребованно?


подумал я тут над этим вопрос, и пришел к выводу — мультиметоды у меня обычно востребованы, когда нужно строить сложные DOM'ы и операции над их элементами. Сюда можно также включить деревья контролов в гуе.
Помимо этого, мультиметоды редко когда нужны.
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re: Насколько необходима множ. диспетчеризация?
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.03.06 21:46
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.


Так как 99% языков без них обходятся, то и говорить не о чем. К тому же как я понимаю, фишки языка вроде сопоставления с образцом могут очень достойно заменять мультиметоды. Вот простенький пример на Нэмерле:
using System.Console;

class A { }

[Record]
class B : A { public Y : string; }

[Record]
class C : A { public Z : int; }

def Func(a1 : A, a2 : A) : void
{
  match ((a1, a2))
  { | (_ is B, _ is C) => WriteLine(":)");
    | (_ is C, _ is B) => WriteLine(":|");
    | _                => WriteLine(":(");
  }
}

Func(B("Test 1"), C(2));
Func(C(2), B("Test 2"));
Func(C(2), A());

Этот код выводит:
:)
:|
:(

что аналогично поведению мультиметодов.
Или вариация с использованием значений:
using System.Console;

class A { }
[Record]
class B : A { public Y : string; }
[Record]
class C : A { public Z : int; }

// Здесь используется неявное сопоставление с обрзцом.
def Func(a1 : A, a2 : A) : void
{ | (b is B, c is C) => WriteLine($"a1.Y='$(b.Y)'  a2.Z=$(c.Z)");
  | (c is C, b is B) => WriteLine($"a1.Z=$(c.Z)  a2.Y='$(b.Y)'");
  | _                => WriteLine(":(");
}

Func(B("Test 1"), C(2));
Func(C(2), B("Test 2"));
Func(C(2), A());

выводит:
a1.Y='Test 1'  a2.Z=2
a1.Z=2  a2.Y='Test 2'
:(


А вот что получается если декомпилировать код в C#:
private static void _N_Func1893(A a1, A a2)
{
    Tuple<A, A> tuple1 = new Tuple<A, A>(a1, a2);
    if (!(tuple1.field0 is B))
    {
        if (!(tuple1.field0 is C))
        {
            goto Label_0093;
        }
        C c1 = (C) tuple1.field0;
        if (!(tuple1.field1 is B))
        {
            goto Label_0093;
        }
        B b1 = (B) tuple1.field1;
        StringBuilder builder2 = new StringBuilder();
        builder2.Append("a1.Z=");
        builder2.Append(c1.Z);
        builder2.Append("  a2.Y='");
        builder2.Append(b1.Y);
        builder2.Append("'");
        Console.WriteLine(builder2.ToString());
        return;
    }
    B b2 = (B) tuple1.field0;
    if (tuple1.field1 is C)
    {
        C c2 = (C) tuple1.field1;
        StringBuilder builder1 = new StringBuilder();
        builder1.Append("a1.Y='");
        builder1.Append(b2.Y);
        builder1.Append("'  a2.Z=");
        builder1.Append(c2.Z);
        Console.WriteLine(builder1.ToString());
        return;
    }
Label_0093:
    Console.WriteLine(":(");
}
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Насколько необходима множ. диспетчеризация?
От: vdimas Россия  
Дата: 02.03.06 08:15
Оценка:
Здравствуйте, Курилка, Вы писали:

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

Соответственно, при арифметических действиях алгоритм и сам результат зависит от взаимных типов операндов. Естественно здесь применить двойную диспечеризацию, но на мультиметодах запись была бы эстетичнее, что ли...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Насколько необходима множ. диспетчеризация?
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.06 22:24
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Естественно, тут у обоих подходов есть и сильные, и слабые стороны.


+1

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

К>Эту неоднозначность разрешают разными способами.
К>Самые распространённые
К>- порядок, определённый пользователем (таблица сопоставления с образцами, собранная вручную)
К>- лексикографический порядок (двойная диспетчеризация; автоматически заполненная таблица)

Кстати, твои слова навели на мысль, что мультиметоды вообще мало применимы в компонентных стистемах, так как они могут содержаться в разных модуля, в том числе и подгружаемых динамически. Это приведет или к неверному поведению, или (при динамической реструктуризации) к нехилым проблемам с логическими ошибками. Так что я уже и не хочу связываться с мультиметодами. Все же то, что код сопоставления в одном месте дает детерминированность. Гибкость мультиметодов может выйти боком.

К>А фишки языка... они большого значения не имеют. Проблема-то именно архитектурная.


Дык если есть сопоставление с образцом, то мы имеем средство для решения большинства задачь без сильных побочных эффектов. А что еще надо?

К>Даже в С++ можем нагородить if(dynamic_cast<X*>(a) && dynamic_cast<Y*>(b))... или что-нибудь подобное. Ну там макросами оформить. В конце концов, MFC строит таблицы виндовских сообщений (кстати, тоже вариация на тему мультиметодов) макросами, и все счастливы.


Счастливы только маньяки или психи. Тот кто видел полноценную компонентную систему построения GUI вряд ли испытает щастье от левой эмуляции на макросах.

Кстати, о чем в MFC ты говоришь как о мультиметодах? О картах сообщений?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Насколько необходима множ. диспетчеризация?
От: Cyberax Марс  
Дата: 03.03.06 09:25
Оценка:
VladD2 wrote:
> Счастливы только маньяки или психи. Тот кто видел полноценную
> компонентную систему построения GUI вряд ли испытает щастье от левой
> эмуляции на макросах.
> Кстати, о чем в MFC ты говоришь как о мультиметодах? О картах сообщений?
Ага. Классическая двойная диспетчеризация — по типу аргумента (коду
сообщения) и по указателю 'this'.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[5]: Насколько необходима множ. диспетчеризация?
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.03.06 12:38
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Ага. Классическая двойная диспетчеризация — по типу аргумента (коду

C>сообщения) и по указателю 'this'.

Хм. Но сообщение является целочисленной константой. То есть второй параметр не полиморфен. Так что это обычный вызов.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Насколько необходима множ. диспетчеризация?
От: Cyberax Марс  
Дата: 03.03.06 12:51
Оценка:
VladD2 wrote:
> C>Ага. Классическая двойная диспетчеризация — по типу аргумента (коду
> C>сообщения) и по указателю 'this'.
> Хм. Но сообщение является целочисленной константой. То есть второй
> параметр не полиморфен. Так что это обычный вызов.
Ну представь, что вместо WM_SETTEXT у тебя объект SetTextMessageData,
унаследованый от MessageData.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re: Насколько необходима множ. диспетчеризация?
От: remark Россия http://www.1024cores.net/
Дата: 08.03.06 02:22
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Собственно сабж.

К>Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.


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

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

Примеров много. Фактически, когда у тебя есть не N действий, а N*M действий в системе — это мультиметод.
Далеко ходить не надо — N типов GUI окон * M типов событий — получается N*M действий. Да это мультиметод, несмотря на то, что мало кто об этом задумывается.

С поддержкой в языке многие вещи стали бы проще (кстати, есть предложение по включению в c++ мультиметодов). Сейчас с ними такая же ситуация, как с динамическим полиморфизмом во время С, когда в языке не было поддержки. Т.е. — реализовывали вручную + многие даже не знали как это называется, просто приходили к такому решению.

Я об этом задумался, когда сам споткнулся на плёвой ситуации — попытался реализовать publisher/subscriber на с++ — не получается. Думаю, чо за фигня — не получается реализовать такую простую вещь. Нет, можно конечно, но для этого надо в интерфейсе ISubscriber сделать по методу для каждого типа события:

struct ISubscriber
{
  virtual void process(Action1&) = 0;
  virtual void process(Action2&) = 0;
  virtual void process(Action3&) = 0;
};


И в каждом действии сделать диспетчер:

struct Action1 : IAction
{
  virtual void dispatch(ISubscriber& subscriber)
  {
     subscriber.process(*this);
  }
};


Тогда работает:

Action1 a;
Subscriber1 s;
a.dispatch(s);


То, что в Action1 надо реализовывать dispatch, это меня ещё устраивало — это можно сделать на шаблонах, но то что в ISubscriber надо прописать по методы на каждое событие, меня не устраивало. Т.к. система задумывалась как расширяемая.

И сейчас в промышленных языках (С++/С#/Java) эту задачу просто не решить (я имею в виду, что решить, но извращаться нужно).

Если бы была поддержка со стороны языка — это бы решалось элементарно — так же как и динамический полиморфизм.


Кстати, если вернуться к MFC и обработке событий окнами. Сейчас мы имеем очень кривую систему — все эти макросы, switch, LPARAM, WPARAM — бред. Если бы в с++ была поддержка мультиметодов, то возможно мы писали бы просто:

class MyWindow : public CDlg
{
...

multimethod void OnMessage(SomeMessageType& msg)
{
   msg.Text = "111";
   msg.Result = true;
   ...
}

...
};


Т.е. — не надо карт событий, не надо всех этих reinterpret_cast, динамического создания/удаления параметров события. Всё было бы красиво, типобезопасно и автоматически.


Вот, что я имел сказать по поводу мультиметодов


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Насколько необходима множ. диспетчеризация?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 08.03.06 20:19
Оценка:
Здравствуйте, remark, Вы писали:

R>Не согласен. Визитор просто позволяет вынести виртуальный метод из иерархии классов в один отдельный класс.


Мы точно под визитором одно и том же понимаем?

R>Нет, его конечно можно назвать мультиметодом для объектов (тип действия, класс),


Мультиметод чистейшей воды, просто реализация несколько неуклюжа.

R> но это называется просто методом. Диспетчерезацию по типу метода всегда выполняет сам программист, когда после точки пишет имя метода.


В классической реализации визитора имя метода Visit всегда одно и то же, а диспетчеризацию выполняет компилятор за счет перегрузки этого метода по типу возвращаемого значения.
... << RSDN@Home 1.2.0 alpha rev. 644 on Windows XP 5.1.2600.131072>>
AVK Blog
Re[4]: Насколько необходима множ. диспетчеризация?
От: VladGalkin Украина  
Дата: 08.03.06 20:30
Оценка:
Здравствуйте, remark, Вы писали:

R>Не согласен. Визитор просто позволяет вынести виртуальный метод из иерархии классов в один отдельный класс.

Но это всё равно, что сказать: "пиво просто позволяет чаще посещать туалет", умолчав о вкусовых качествах этого напитка.
Одна из основных идея visitor'а — именно полиморфизм со множественной диспетчеризацией. Можете вот книжку Александреску почитать про это.
... << RSDN@Home 1.1.4 stable rev. 510>>
ДЭ!
Re[2]: Насколько необходима множ. диспетчеризация?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 08.03.06 20:34
Оценка:
Здравствуйте, remark, Вы писали:

R>И сейчас в промышленных языках (С++/С#/Java) эту задачу просто не решить (я имею в виду, что решить, но извращаться нужно).


На C# эта задача просто решается без каких либо извращений при помощи атрибутов и делегатов. Вот реальный код, использующий это:
internal class TagLineListForm : Form
{
    public TagLineListForm()
    {
        ...

        _toolStrip.Items.AddRange(
            StripSerializer.LoadFromXmlWithDispatch(
                typeof (TagLineListForm).Assembly.GetManifestResourceStream(
                    "Rsdn.Janus.Features.MessageEditor.TagLine.EditorToolbar.xml"),
                this, // передаем указатель на обработчик типа object
                true));
                
        ...
    }

    [StripEventHandler("del")]
    private void DeleteTagLine()
    {
        ...
    }

    [StripEventHandler("edit")]
    private void EditTagLine()
    {
        ...
    }

    [StripEventHandler("add")]
    private void AddTagLine()
    {
        ...
    }
}

<items>
    <button text="Config.TagLine.Editor.Add" event-id="add" image="new"/>
    <button text="Config.TagLine.Editor.Edit" event-id="edit" image="editmsg"/>
    <button text="Config.TagLine.Editor.Delete" event-id="del" image="del"/>
</items>

Как видишь, без проблем обошлись без мультиметодов, встроенных в язык.
... << RSDN@Home 1.2.0 alpha rev. 644 on Windows XP 5.1.2600.131072>>
AVK Blog
Re[5]: Насколько необходима множ. диспетчеризация?
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.03.06 21:22
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>В классической реализации визитора имя метода Visit всегда одно и то же, а диспетчеризацию выполняет компилятор за счет перегрузки этого метода по типу возвращаемого значения.


Классических вариантов два. Один с перегрузкой, другой нет. Я видил даже где-то спор как лучше методы называть. Одни орали, что перегрузка удобнее, а другие, что мол так понятнее.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Насколько необходима множ. диспетчеризация?
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.03.06 21:22
Оценка:
Здравствуйте, VladGalkin, Вы писали:

VG>Одна из основных идея visitor'а — именно полиморфизм со множественной диспетчеризацией. Можете вот книжку Александреску почитать про это.


В Посетителе диспечерезация двойная (по типу объекта коллекции и по типу объекта которому передается обработка). Это конечто наверно относится к множественной диспечеризации, но это все же частный случай.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Насколько необходима множ. диспетчеризация?
От: VladGalkin Украина  
Дата: 09.03.06 07:15
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>В Посетителе диспечерезация двойная (по типу объекта коллекции и по типу объекта которому передается обработка). Это конечто наверно относится к множественной диспечеризации, но это все же частный случай.


Частный случай, но уже множественной диспетчеризации . Если не изменяет память, тот же Александреску делал Visitor с более чем двойной диспетчеризацией, с помощью TypeList'ов, хотя кто его знает...
... << RSDN@Home 1.1.4 stable rev. 510>>
ДЭ!
Re: Простой пример
От: fionbio  
Дата: 10.03.06 07:50
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Собственно сабж.

К>Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.

Простой, может быть, конечно, несколько дурацкий пример — GUI'шная либа со стилями. Подобная
задача обычно решается при помощи visitor / acyclic visitor, и выходит достаточно неудобоваримо.
Есть набор контролов (или виджетов, кому как больше нравится) — кнопка, поле ввода, скроллбар и пр.,
а также набор стилей — виндоус, аква, мотиф и пр. Стиль имеет вид вроде

public class Style: BaseStyle
{
  ...

  public override void Paint(Button button, ...)
  {
    ...
  }

  public override void Paint(TextBox textBox, ...)
  {
    ...
  }

  public override void Paint(ScrollBar scrollBar, ...)
  {
    ...
  }

  ...
}


соответственно в каждом контроле есть метод Paint, например

public class Button: Control
{
  ...
  public override void Paint(Style style, ...)
  {
    style.Paint(this, ...)
  }
  ...
}


Это, собственно, визитор — вызов style.Paint выбирает нужный метод
через оверлоадинг в период компиляции. В чём неудобство?
Допустим, пользователю библиотеки надо добавить ещё какой-то контрол,
например, PornView. Более того, допустим, у пользователя библиотеки есть чёткое
представление, как этот контрол должен выглядеть в стиле виндоус, аква
и пр. Что придётся делать пользователю? Извращаться — ведь интерфейс
стиля не расширишь, придётся проверять тип стиля в Paint, затем
для каждого стиля рисовать по-своему, или ещё что похуже. Нету в
BaseVisitor метода Paint(PornView pornView, ...), и ничего тут неэ
попишешь. Библиотеку менять нельзя. В общем, фигня. Подобные вещи
можно до какой-то степени облегчить при помощи Acyclic Visitor, но
это тоже не фунт изюму, и потом ещё в этом самому разбираться
придётся...

Рассмотрим, как такое решается в языке с поддержкой мультиметодов —
например, Common Lisp. (троеточия здесь, как и в случае C#, не являются
синтаксической конструкцией, а обозначают опущенные параметры)

Есть generic function, вообще не привязанный ни к какому классу:
(defgeneric paint (style control ...)
  (:documentation "Paint the CONTROL using STYLE"))


Когда делается контрол, к нему приделывается дефолтный метод
рисования, который вызывается, когда специфического метода для
данного стиля не определено. В этом случае отрисовка идёт самым
простым путём — чтоб хоть как-то отрисовать. Например, для кнопки

(defmethod paint (style (control button) ...)
  ;; рисуем плоскую некрасивую кнопку
  ...)


или для скроллбара

(defmethod paint (style (control scrollbar) ...)
  ;; рисуем плоский некрасивый скроллбар
  ...)


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

Когда делаются стили, то в них описываются методы отрисовки известных
контролов, например для аквы

(defmethod paint ((style aqua) (conrol button) ...)
  ;; рисуем водянистую кнопку
  ...)

(defmethod paint ((style aqua) (conrol scrollbar) ...)
  ;; рисуем водянистый скроллбар
  ...)

(defmethod paint ((style aqua) (conrol textbox) ...)
  ;; рисуем водянистый текстбокс
  ...)


или для виндоус

(defmethod paint ((style windows) (conrol button) ...)
  ;; рисуем виндообразную кнопку
  ...)

(defmethod paint ((style windows) (conrol scrollbar) ...)
  ;; рисуем виндообразный скроллбар
  ...)

(defmethod paint ((style windows) (conrol textbox) ...)
  ;; рисуем виндообразный текстбокс
  ...)


Когда пользователь делает контрол porn-view, он может
сопроводить его не только дефолтной рисовалкой

(defmethod paint (style (control porn-view) ...)
  ;; нарисовать по-простому
  ...)


но и набором рисовалок для ряда стилей, например

(defmethod paint ((style aqua) (control porn-view) ...)
  ;; нарисовать porn-view по-водянистому
  ...)

(defmethod paint ((style windows) (control porn-view) ...)
  ;; нарисовать porn-view по-виндовски
  ...)

(defmethod paint ((style motif) (control porn-view) ...)
  ;; нарисовать porn-view на мотив мотифа
  ...)


в свою очередь, если какой-либо ещё дядя вася использует
основную библиотеку, контрол porn-view и ещё одну либу с набором
стилей, и ему не нравится, что в стиле super-puper porn-view
рисуется по-дефолтному, он может дописать

(defmethod paint ((style super-puper) (control porn-view) ...)
  ;; нарисовать porn-view в стиле супер-пупер
  ...)


В общем, экстенсибилити не знает границ
В языках типа C# можно ещё извращаться с Reflection, всякие
Type.InvokeMember, но гораздо приятнее, когда есть поддержка языка.
Re: Насколько необходима множ. диспетчеризация?
От: Gaperton http://gaperton.livejournal.com
Дата: 10.03.06 14:38
Оценка:
Здравствуйте, Курилка, Вы писали:

К>Собственно сабж.

К>Много читал про то, что в ряде языков мультиметоды реализуются в самом языке (CLOS, Cecil, Dylan, Self), только разбираемые примеры выглядят несколько искуственными с той точки зрения, что подобные задачи (когда результат определяется как некое "пересечение" 2-х и более типов объектов) встречаются, на мой взгляд, относительно редко. Поэтому есть мысль, что, несмотря на крутость "встроенности" мультиметодов, в реальной жизни они не так часто дают выгоду, т.к. являются интересной фенечкой лишь иногда позволяющей изящно решить задачу.

Мультиметоды применяются во всех случаях, когда ты используешь double dispatch. Необходимость в нем возникает, например, когда ты хочешь по человечески реализовать конечный автомат в духе ООП. И это не единственный пример — их дофига.

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

Мультиметоды решают эту проблему, устраняя вредный паттерн проектирования.
Re[3]: Насколько необходима множ. диспетчеризация?
От: remark Россия http://www.1024cores.net/
Дата: 22.04.06 22:54
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, remark, Вы писали:


R>>И сейчас в промышленных языках (С++/С#/Java) эту задачу просто не решить (я имею в виду, что решить, но извращаться нужно).


AVK>На C# эта задача просто решается без каких либо извращений при помощи атрибутов и делегатов. Вот реальный код, использующий это:


[skip]

AVK>Как видишь, без проблем обошлись без мультиметодов, встроенных в язык.


Ну возможно я немного загнул по поводу других языков, кроме с++. У C# тоже (как и у С++) есть много очень сильных сторон (в плане реализации интересных/полезных моментов). Это я полностью согласен.

А, кстати, в приведённом тобой примере можно с событием типобезопасно передать и произвольный объект с параметрами?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Насколько необходима множ. диспетчеризация?
От: Дарней Россия  
Дата: 23.04.06 06:19
Оценка:
Здравствуйте, remark, Вы писали:

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


у GOF прямо написано, что визитор — это эмуляция множественной диспетчеризации, которая в других языках поддерживается напрямую. И в качестве примера приводится CLOS. О чем тут спорить то?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[4]: Насколько необходима множ. диспетчеризация?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.04.06 14:08
Оценка:
Здравствуйте, remark, Вы писали:

R>А, кстати, в приведённом тобой примере можно с событием типобезопасно передать и произвольный объект с параметрами?


Соответствие типов обеспечивается только в рантайме.
... << RSDN@Home 1.2.0 alpha rev. 646 on Windows XP 5.1.2600.131072>>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.