Насколько необходима множ. диспетчеризация?
От: Курилка Россия 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: Насколько необходима множ. диспетчеризация?
От: 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[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[3]: Насколько необходима множ. диспетчеризация?
От: Oyster Украина https://github.com/devoyster
Дата: 27.02.06 09:07
Оценка: 1 (1)
Здравствуйте, Курилка, Вы писали:

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


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

С другой стороны, возможно, я просто не умею её готовить и поэтому не использую, хотя мог бы.
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[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[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[2]: Насколько необходима множ. диспетчеризация?
От: Кодт Россия  
Дата: 01.03.06 23:19
Оценка: 35 (4) +1
Здравствуйте, VladD2, Вы писали:

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


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

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

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

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

Даже в С++ можем нагородить if(dynamic_cast<X*>(a) && dynamic_cast<Y*>(b))... или что-нибудь подобное. Ну там макросами оформить. В конце концов, MFC строит таблицы виндовских сообщений (кстати, тоже вариация на тему мультиметодов) макросами, и все счастливы.
Перекуём баги на фичи!
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[6]: Насколько необходима множ. диспетчеризация?
От: Кодт Россия  
Дата: 03.03.06 13:06
Оценка: +3
> C>Ага. Классическая двойная диспетчеризация — по типу аргумента (коду
> C>сообщения) и по указателю 'this'.
>
> Хм. Но сообщение является целочисленной константой. То есть второй параметр не полиморфен. Так что это обычный вызов.

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

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


К>Не спорю



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



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
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
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.