Мультиметоды и Nemerle
От: Anton V. Kolotaev  
Дата: 16.04.06 16:49
Оценка:
Реально ли на макросах Nemerle изобразить мультиметоды?
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re: Мультиметоды и Nemerle
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 16.04.06 17:46
Оценка: +2
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Реально ли на макросах Nemerle изобразить мультиметоды?


Реально, но смысла нет. Паттерн-матчинг покрывает все возможные их применения.
... << RSDN@Home 1.2.0 alpha rev. 646 on Windows XP 5.1.2600.131072>>
AVK Blog
Re[2]: Мультиметоды и Nemerle
От: Anton V. Kolotaev  
Дата: 16.04.06 18:11
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>>Реально ли на макросах Nemerle изобразить мультиметоды?


AVK>Реально, но смысла нет. Паттерн-матчинг покрывает все возможные их применения.


Как я понял, альтернативы в паттерн-матчинге перебираются в порядке их объявления и таким образом может быть отдано предпочтение менее специализированной альтернативе, если она определена раньше более специализированной альтернативы. Когда речь идет о мультиметодах подразумевается, что вызывается наиболее специализированный метод (если нет неоднозначностей).
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re[3]: Мультиметоды и Nemerle
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 16.04.06 18:26
Оценка:
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Как я понял, альтернативы в паттерн-матчинге перебираются в порядке их объявления и таким образом может быть отдано предпочтение менее специализированной альтернативе, если она определена раньше более специализированной альтернативы.


Все это решаемо, к примеру, добавлением параметра в паттерн-матчинге, управляющего выбором альтернатив более точно.

AVK> Когда речь идет о мультиметодах подразумевается, что вызывается наиболее специализированный метод (если нет неоднозначностей).


Тут я плохо знаком с Nemerle, но, к примеру, в CSS или XSLT тоже выбирается наиболее специализированная альтернатива.
... << RSDN@Home 1.2.0 alpha rev. 646 on Windows XP 5.1.2600.131072>>
AVK Blog
Re[4]: Мультиметоды и Nemerle
От: Anton V. Kolotaev  
Дата: 16.04.06 18:35
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>>Как я понял, альтернативы в паттерн-матчинге перебираются в порядке их объявления и таким образом может быть отдано предпочтение менее специализированной альтернативе, если она определена раньше более специализированной альтернативы.


AVK>Все это решаемо, к примеру, добавлением параметра в паттерн-матчинге, управляющего выбором альтернатив более точно.


Если не сложно, можно ли привести примерчик, а то я не совсем понял, что Вы имеете в виду.
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re: Мультиметоды и Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.04.06 19:32
Оценка: 6 (1)
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Реально ли на макросах Nemerle изобразить мультиметоды?


Мультиметоды — это средство обеспечения диспечеризации по нескольким полиморфным параметрам. При чистой реализации мультиметодов возникает ряд проблем:
1. Мултиметоды конфликтуют с перегрузкой (статическим полиморфизмом).
2. Мултиметоды подразумевают то, что новые реализации методов могут появиться в рантайме, например, в следствии загрузки новой библиотеки.

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

АВК правильно сказал, что ту же задачу "диспечеризацию по нескольким полиморфным параметрам" можно решить сопостовлением с образцом. При оно уже есть, отлично работает и прекрасно вписывается в концепции языка.

Так что полностью согласен с АВК, "патерн-матчинг" с успехом заменяет мультиметоды в рельной жизни. Так что нужды в них просто нет.

Тем не менее конечно можно написать некие макросы эмулирующие поведение мультиметодов. Технически проблема решаема.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Мультиметоды и Nemerle
От: Anton V. Kolotaev  
Дата: 16.04.06 19:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Мультиметоды — это средство обеспечения диспечеризации по нескольким полиморфным параметрам. При чистой реализации мультиметодов возникает ряд проблем:

VD>1. Мултиметоды конфликтуют с перегрузкой (статическим полиморфизмом).

Не совсем понимаю, как они могут неразрешимо конфликтовать.

VD>2. Мултиметоды подразумевают то, что новые реализации методов могут появиться в рантайме, например, в следствии загрузки новой библиотеки.


Значит и таблица диспетчеризации тоже должна корректироваться в рантайме и быть реализована, видимо, через какую-то хитрую структуру данных. Естественно, скорость виртуального вызова по ней будет ниже чем если бы мы знали все входящие в нее методы в момент компиляции.
... << RSDN@Home 1.2.0 alpha rev. 648>>
Re[3]: Мультиметоды и Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.04.06 20:21
Оценка: 3 (1)
Здравствуйте, Anton V. Kolotaev, Вы писали:

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


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

Вот простой пример эмуляции мультиметодов:
using System.Console;

variant Foo
{
  | A { x : int; }
  | B
}

def MiltiDispatch(x : Foo, y : Foo)
{ | (A as a, B) when a.x > 0 => WriteLine($"A, B (a.x=$(a.x))");
  | (A, B)                   => WriteLine("A, B");
  | (A, A)                   => WriteLine("A, A");
  | (B, A)                   => WriteLine("B, A");
  | (B, B)                   => WriteLine("B, B");
}

MiltiDispatch(Foo.A(0), Foo.B());
MiltiDispatch(Foo.A(2), Foo.B());
MiltiDispatch(Foo.B(),  Foo.B());

Он прекрасно компилируется и работает. Если переместить строчку
 | (A as a, B) when a.x > 0 => WriteLine($"A, B (a.x=$(a.x))");

ниже...
using System.Console;

variant Foo
{
  | A { x : int; }
  | B
}

def MiltiDispatch(x : Foo, y : Foo)
{ | (A, B)                   => WriteLine("A, B");
  | (A, A)                   => WriteLine("A, A");
  | (B, A)                   => WriteLine("B, A");
  | (A as a, B) when a.x > 0 => WriteLine($"A, B (a.x=$(a.x))");
  | (B, B)                   => WriteLine("B, B");
}

MiltiDispatch(Foo.A(0), Foo.B());
MiltiDispatch(Foo.A(2), Foo.B());
MiltiDispatch(Foo.B(),  Foo.B());

... то компилятор выдаст предупреждение:
Main.n(13,5,13,16): warning : this match clause is unused
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Мультиметоды и Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.04.06 20:37
Оценка: 13 (2)
Здравствуйте, Anton V. Kolotaev, Вы писали:

VD>>1. Мултиметоды конфликтуют с перегрузкой (статическим полиморфизмом).


AVK>Не совсем понимаю, как они могут неразрешимо конфликтовать.


Ну, давай помечтаем. Предположим, что у нас есть иерархия типов:
class A { }
class B : A { }
class C : B { }
class D : B { }


Теперь мы обявляем два мультиметода:
void Method1(virtual x : D, virtual c : C) { ... }
void Method1(        x : B,         c : C) { ... }

Теперь мы вызваем метод:
def b : B = D();
Method1(b, C());

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

Компилятор конечно может разрешить конфликт придерживаясь некой стратегии, но для человека это будет понять очень не просто.

А учитывая, что в последствии может появится еще одна версия метода все становится еще печальнее.

Так что не факт, что такое решение будет благом. Вернее почти факт, что вреда будет больше.

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

VD>>2. Мултиметоды подразумевают то, что новые реализации методов могут появиться в рантайме, например, в следствии загрузки новой библиотеки.


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


Ага. Но это технический аспект. Намного важнее аспект понимния людми. Аспект контроля ситуации. Я личо буду чувствовать себя не уютно когда любой урод сможет внести хаос в казалось бы отлаженный код. Если мне нужна настраиваемость, то я предпочитаю явно ее оговорить. В случае паттерн-матчинга я могу просто сделать пункт:
_ => CallSomeFunctionalValue()

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

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


Скорость здесь не самый важный аспкт, но и он проще решается в детерминированной среде.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Мультиметоды и Nemerle
От: Anton V. Kolotaev  
Дата: 17.04.06 06:58
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, давай помечтаем. Предположим, что у нас есть иерархия типов:

VD>
VD>class A { }
VD>class B : A { }
VD>class C : B { }
VD>class D : B { }
VD>


VD>Теперь мы обявляем два мультиметода:

VD>
VD>void Method1(virtual x : D, virtual c : C) { ... }
VD>void Method1(        x : B,         c : C) { ... }
VD>

VD>Теперь мы вызваем метод:
VD>
VD>def b : B = D();
VD>Method1(b, C());
VD>

VD>С точки зрения статического полиморфизма (перегрузки) компилятор должен подставить вызов первого метода, но динамический тип все же D.

Если вызов статический, то будет все-таки вызван второй вариант.

VD>Компилятор конечно может разрешить конфликт придерживаясь некой стратегии, но для человека это будет понять очень не просто.


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

class A {}
class B  : A {}

void f(virtual x : A, virtual y : A) { ... }   // (1)
void f(virtual x : A, virtual y : B) { ... }   // (2)
void f(virtual x : B, virtual y : A) { ... }   // (3)

void g()
{
    def a : A = B();
    f(a, a); // статически будет выбрана функция (1), а в динамике произойдет конфликт между (2) и (3)
}


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

VD>С паттерн-матчингом же все очевидно. Есть единое место где описывается диспетчерезация, нет проблем в понимании и разных неявных эффектов.


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

VD>Если мне нужна настраиваемость, то я предпочитаю явно ее оговорить. В случае паттерн-матчинга я могу просто сделать пункт:

VD>
VD>_ => CallSomeFunctionalValue()
VD>

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

Если имеется в виду, что CallSomeFunctionalValue -- это зацепка, которую разработчик библиотеки предоставляет пользователю для перекрытия, то она должна принимать все те же два аргумента, что и библиотечная функция, т.е. проблема мультиметодов возникает опять.
... << RSDN@Home 1.2.0 alpha rev. 648>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.