Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Можно ввести общий интерфейс I содержащий только M2 и параметризовать класс им.
Это можно в моем надуманном примере, а если ты должен использовать "чужие" интерфейсы, то не можно. Да, к тому же мне и остальные методы интерфейсов нужны.
LCR>Кроме того, то, что указанный вызов не кушается компилятором, это не слишком большая проблема. Получается просто некрасиво, но не более того (могло бы быть сгенерировано компилятором). LCR>
Отличный пример того, что интерфейсы пока не тянут на понятие контракт. Ты взял да попытался разрисовать механику (ибо по-другому — никак). Более того, налицо побочные эффекты: результат может измениться, если в if() ты сначала проверишь _f2. Я уже молчу о том, что приведенный код содержит откровенный ляп, что так же весьма показательно. (вернее так: приведенный код — это попытка озвучить софизм на императивном ЯП, присмотрись внимательно, что ты там накуролесил в этих 6-ти строчках )
Вот тебе и "контракты" на базе интерфейсов.
V>>"Чистые" контракты могли бы быть лишены всеего этого багажа непродумманости. V>>Более того, над контрактами можно было бы выполнять операции как над множествами: объединять, вычитать, находить разность и т.д. Результатом подобных операций был бы новый контракт.
LCR>Я продолжу. Контракты потом захочется организовывать в коллекции, чтобы автоматизировать вещи типа $\Cup_i C_i$.
Контракт — это уже и есть коллекция, вернее множество. Некое множество ограничений.
Кстати, вспомнил еще кое-что. До меня доходили слухи, что в каком-нибудь C# XX.0 делегаты будут совместимы м/у собой по сигнатурам, а так же можно будет вешать делегаты на пропертя, и вообще планнируют пару подпорок для ФЯ. Для того, чтобы это стало возможным, им придется ввести еще одну сущность — "сигнатура". Так вот, представление типа обсуждаемого контракта можно было бы свести к коллекции (множеству) этих "сигнатур".
LCR>Уже целый язык получается (на ум приходят аналогии с xpath и sql).
Твои xpath и sql уже встроены в C#-подобный язык.
LCR>Картина получается слишком сложной, имхо.
А ну да... как же без этого крайне ценного замечания... А на мой взгляд на порядок проще чем LINQ, да и руки развяжет основательно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[22]: Философический вопрос про автоматический вывод типов
vdimas,
V>Я уже молчу о том, что приведенный код содержит откровенный ляп, что так же весьма показательно.
Да, _f2 может быть null.
LCR>>Я продолжу. Контракты потом захочется организовывать в коллекции, чтобы автоматизировать вещи типа $\Cup_i C_i$. V>Контракт — это уже и есть коллекция, вернее множество. Некое множество ограничений.
Может потребоваться множество множеств. В самом деле, почему нет? Естественно и операции над ним. Скажем, контракты C0, C1, C2, C3. Мы можем ручками:
interface Ix : D diff (C0 or C1 or C2 or C3) {}
А можно обобщить эту картину на случай не только n=3, параметризовав C. Потребуется некий конструкт, коллекция этих C_i. Вот я о чём.
Ещё есть одно ограничение, которое хотелось всегда иметь: notnull. Твои контракты не потянут это ограничение, потому что интерфейс не может его (ограничение) отразить.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
V>>Я уже молчу о том, что приведенный код содержит откровенный ляп, что так же весьма показательно.
LCR>Да, _f2 может быть null.
Опять не угадал. У нас I1 и I2 — ограничения дженерика. Соответственно требуемый тип реализует ОБА интерфейса. Это значит, что _f1 и _f2 либо одновременно равны null в твоем примере, либо оба не равны. Ставить там if() на проверку _f1 или _f2 — абсурд.
LCR>>>Я продолжу. Контракты потом захочется организовывать в коллекции, чтобы автоматизировать вещи типа $\Cup_i C_i$. V>>Контракт — это уже и есть коллекция, вернее множество. Некое множество ограничений. LCR>Может потребоваться множество множеств. В самом деле, почему нет? Естественно и операции над ним. Скажем, контракты C0, C1, C2, C3. Мы можем ручками: LCR>
LCR>interface Ix : D diff (C0 or C1 or C2 or C3) {}
LCR>
LCR>А можно обобщить эту картину на случай не только n=3, параметризовав C. Потребуется некий конструкт, коллекция этих C_i. Вот я о чём.
Знаешь, меня бы на ближайшие лет 10 устроило бы хотя бы простое объединение, такое же как в случае нынешних интерфейсов:
class MyClass<T> where T : C0<T>, C1<T>, C2<T> { ... }
LCR>Ещё есть одно ограничение, которое хотелось всегда иметь: notnull. Твои контракты не потянут это ограничение, потому что интерфейс не может его (ограничение) отразить.
Это ограничени из области run-time, а не compile-time. Есть компилятор C#, который умеет обрабатывать дополнительный набор аттрибуттов и генерировать код для подобной проверки.
Авообще, самое замечательное ограничение notnull в дотнете — это использовать value-типы, что я и делаю часто и охотно. Кстати, в дженериках так же можно задать ограничение на ValueType.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[24]: Философический вопрос про автоматический вывод типов
vdimas,
LCR>>Да, _f2 может быть null.
V>Опять не угадал. У нас I1 и I2 — ограничения дженерика. Соответственно требуемый тип реализует ОБА интерфейса. Это значит, что _f1 и _f2 либо одновременно равны null в твоем примере, либо оба не равны. Ставить там if() на проверку _f1 или _f2 — абсурд.
Здравствуйте, vdimas, Вы писали: V>Казалось бы, все вполне логично с т.з. проектирования абстракций. Только не компилится... и вот только попробуй мне сказать, что ситуацию в этом примере спасет явное приведение к одному из интерфейсов... какое нафиг может быть преобразование типа к ограничению???!!!
По-моему, ты гонишь. Ты ввел два совершенно разных метода: I1.M2 и I2.M2. Тут и без дженерика неясно, что ты имеешь в виду. Точнее, при использовании "настоящего" типа у компилятора есть средство разрулить неопределенность.
Вот тебе пример класса, которым я параметризую твой дженерик:
public class Crach: I1, I2
{
public void M1() { Console.Write("I1M1");}
void I1.M2() { Console.Write("I1M2");}
void I2.M2() { Console.Write("I2M2");}
public void M3() { Console.Write("I2M3");}
}
Что должен вывести вызов new Class1<Crash>.MM()? V>"Чистые" контракты могли бы быть лишены всеего этого багажа непродумманости.
Да-да-да. Я прямо так и вижу этот багаж непродуманности. Вот когда ты отмедитируешь над тем, что нужно делать в таком случае, расскажи мне. V>Более того, над контрактами можно было бы выполнять операции как над множествами: объединять, вычитать, находить разность и т.д. Результатом подобных операций был бы новый контракт.
Это все — дак тайпинг, что ты только что продемонстрировал своим примером.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Философический вопрос про автоматический вывод типов
Здравствуйте, Sinclair, Вы писали:
V>>Казалось бы, все вполне логично с т.з. проектирования абстракций. Только не компилится... и вот только попробуй мне сказать, что ситуацию в этом примере спасет явное приведение к одному из интерфейсов... какое нафиг может быть преобразование типа к ограничению???!!! S>По-моему, ты гонишь. Ты ввел два совершенно разных метода: I1.M2 и I2.M2. Тут и без дженерика неясно, что ты имеешь в виду.
По моему, ты слишком увлекся особенностями реализации контрактов в дотнете, не находишь? Иначе бы не приводил код с явной имплементацией интерфейсов в обсуждении применимости интерфейсов как контрактов. Ты лишь продемонстрировал, что интерфейсы плохо для этого подходят.
Ты бы хоть задумался — в каком случае тебе потребуются отдельные явные имплементации методов M2 в разных интерфейсах? Очевидно, в случае обладания разной семантикой. Сильная семантическая нагрузка на интерфейсы (как на самодостаточные наборы сигнатур) в дотнете не от хорошей жизни, а от отсутствия МН. В дотнете такую сущность как "интерфейс" зачастую выбирают для описания корня иерархии некоторого семейства, хотя корнем ИМХО должен был бы быть некий базовый класс, а не интерфейс (где сказано, что базовый класс не может обладать базовой функциональностью? да он обязан ею обладать).
Если же продолжать обсуждать контракты, то понятие "контракт" немного слабее, что-ли, чем понятие "сущность", которую несут в себе интерфейсы в дотнете сейчас. Например, мне для алгоритма надо, чтобы некий экземпляр обладал св-вом Count. Да, достаточно чтобы просто одним этим св-вом. Не думаю, что при "пересечении" этого св-ва у разных ограничений (интерфейсов или контрактов) должны возникать семантические конфликты. Уверен, контракты именно будут проектироватьименно таким образом, дабы минимизировать вероятность столкновений.
S>Это все — дак тайпинг, что ты только что продемонстрировал своим примером.
Вот ты и гонишь со своим дак-тайпингом. Где ты увидел "недотипизированность" или динамическую типизированность? VM при загрузке типа будет параметризировать дженерик конкретным типом, все связи будут "бинарные и жесткие". А то с твоих слов выходит, что шаблоны в С++ — это тоже дак-тайпинг, ведь там даже контракты задавать не надо — пихай что хочешь... Хотя мне эти шаблоны помогали имено жестче типизировать абстракции и обкладываться ограничениями. (про С++ разговор особый, как всегда недостающие фичи легко реализуются в нем ср-вами языка, например ограничения шаблонов или контракты... не бинарные интерфейсы, а именно контракты ).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[22]: Философический вопрос про автоматический вывод типов
Здравствуйте, vdimas, Вы писали: V>По моему, ты слишком увлекся особенностями реализации контрактов в дотнете, не находишь? Иначе бы не приводил код с явной имплементацией интерфейсов в обсуждении применимости интерфейсов как контрактов. Ты лишь продемонстрировал, что интерфейсы плохо для этого подходят.
Наверное, увлекся. V>Ты бы хоть задумался — в каком случае тебе потребуются отдельные явные имплементации методов M2 в разных интерфейсах? Очевидно, в случае обладания разной семантикой.
Совершенно верно. И все-таки, объясни мне, какой именно метод должен вызываться в данном случае?
Или ты предлагаешь вернуться к плюсам, где невозможно реализовать семантически различные методы с одинаковой сигнатурой? Ты так и не ответил, какой именно код должен исполняться в приведенном мной случае. А если ты честно ответишь на этот вопрос, то поймешь, что без явной квалификации интерфейса не обойтись. А то, что в шарпе нет специального синтаксиса, как в плюсах, так это ерунда — семантика-то та же. V>Сильная семантическая нагрузка на интерфейсы (как на самодостаточные наборы сигнатур) в дотнете не от хорошей жизни, а от отсутствия МН. В дотнете такую сущность как "интерфейс" зачастую выбирают для описания корня иерархии некоторого семейства, хотя корнем ИМХО должен был бы быть некий базовый класс, а не интерфейс (где сказано, что базовый класс не может обладать базовой функциональностью? да он обязан ею обладать).
Ничего не понимаю. Почему это корня? Множественное наследование в дотнете присутствует, и именно в интерфейсах. Никогда не видел, чтобы именно интерфейс в дотнете выбирали в качестве корня иерархии. Классы — да: вот например нету ни IStream, ни ITextReader. V>Если же продолжать обсуждать контракты,
Не надо обсуждать контракты. Чтобы то, что ты предлагаешь, хоть как-то заработало, нужно отказаться от дотнета. Ок, мне не оченm интересно обсуждать перспективы альтернативных технологий. V>то понятие "контракт" немного слабее, что-ли, чем понятие "сущность", которую несут в себе интерфейсы в дотнете сейчас. Например, мне для алгоритма надо, чтобы некий экземпляр обладал св-вом Count. Да, достаточно чтобы просто одним этим св-вом. Не думаю, что при "пересечении" этого св-ва у разных ограничений (интерфейсов или контрактов) должны возникать семантические конфликты. Уверен, контракты именно будут проектироватьименно таким образом, дабы минимизировать вероятность столкновений.
А зачем? S>>Это все — дак тайпинг, что ты только что продемонстрировал своим примером. V>Вот ты и гонишь со своим дак-тайпингом. Где ты увидел "недотипизированность" или динамическую типизированность?
Как это? Дак-тайпинг — это и есть "наличие подходящих методов". Вместо точной сигнатуры, как у интерфейсов. V>VM при загрузке типа будет параметризировать дженерик конкретным типом, все связи будут "бинарные и жесткие". А то с твоих слов выходит, что шаблоны в С++ — это тоже дак-тайпинг, ведь там даже контракты задавать не надо — пихай что хочешь... Хотя мне эти шаблоны помогали имено жестче типизировать абстракции и обкладываться ограничениями. (про С++ разговор особый, как всегда недостающие фичи легко реализуются в нем ср-вами языка, например ограничения шаблонов или контракты... не бинарные интерфейсы, а именно контракты ).
Совершенно верно, шаблоны в плюсах — это дак-тайпинг. А ты не знал?
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Философический вопрос про автоматический вывод типов
V>>Ты бы хоть задумался — в каком случае тебе потребуются отдельные явные имплементации методов M2 в разных интерфейсах? Очевидно, в случае обладания разной семантикой. S>Совершенно верно. И все-таки, объясни мне, какой именно метод должен вызываться в данном случае?
Метод Class1.M2 разумеется, единственный и неповторимый . Речь же о контракте. Я же не обсуждаю текущую реализацию интерфейсов в дотнете, я пытаюсь объяснить, почему иногда мне было бы удобно использовать контракты там, где мы вынуждены использовать интерфейсы. Через контракты, например, можно было бы требовать ниличия даже СТАТИЧЕСКИХ методов, а значит... да именно, перегруженных операторов (согласись, дженерики смотрятся бледновато без них).
S>Или ты предлагаешь вернуться к плюсам, где невозможно реализовать семантически различные методы с одинаковой сигнатурой?
Нет, не предлагаю. Пусть для интерфейсов все останется как есть. Интерфейсы очень эффективно используются для осуществления бинарной совместимости. Ведь в С++ тоже вовсю успешно применяются полностью абстрактные классы (аналоги интерфейсов) именно там, где они нужны. Мы ведь обсуждали способ задания ограничений в дженериках, ты не забыл? А это несколько "другой" способ использования интерфейсов, чем то, про что ты сейчас говорил.
S>Ты так и не ответил, какой именно код должен исполняться в приведенном мной случае.
В твоем коде и при использовании интерфейсов — не знаю Надо явно указывать и это зависит от семантик интерфейсов.
А при использовании контрактов — Class1.M2
S>А если ты честно ответишь на этот вопрос, то поймешь, что без явной квалификации интерфейса не обойтись.
И я о том же, ну неудобно их юзать для ограничений дженериков.
V>>Сильная семантическая нагрузка на интерфейсы (как на самодостаточные наборы сигнатур) в дотнете не от хорошей жизни, а от отсутствия МН. В дотнете такую сущность как "интерфейс" зачастую выбирают для описания корня иерархии некоторого семейства, хотя корнем ИМХО должен был бы быть некий базовый класс, а не интерфейс (где сказано, что базовый класс не может обладать базовой функциональностью? да он обязан ею обладать). S>Ничего не понимаю. Почему это корня? Множественное наследование в дотнете присутствует, и именно в интерфейсах. Никогда не видел, чтобы именно интерфейс в дотнете выбирали в качестве корня иерархии. Классы — да: вот например нету ни IStream, ни ITextReader.
Зато полно IDbConnection, IDbTransaction и прочее, и прочее...
S>Не надо обсуждать контракты. Чтобы то, что ты предлагаешь, хоть как-то заработало, нужно отказаться от дотнета. Ок, мне не оченm интересно обсуждать перспективы альтернативных технологий.
2 года назад я слышал подобное о шаблонах в дотнете. И что? Никто не отказался. Реализовали дженерики, и расширили возможности среды.
V>>то понятие "контракт" немного слабее, что-ли, чем понятие "сущность", которую несут в себе интерфейсы в дотнете сейчас. Например, мне для алгоритма надо, чтобы некий экземпляр обладал св-вом Count. Да, достаточно чтобы просто одним этим св-вом. Не думаю, что при "пересечении" этого св-ва у разных ограничений (интерфейсов или контрактов) должны возникать семантические конфликты. Уверен, контракты именно будут проектироватьименно таким образом, дабы минимизировать вероятность столкновений. S>А зачем? S>>>Это все — дак тайпинг, что ты только что продемонстрировал своим примером. V>>Вот ты и гонишь со своим дак-тайпингом. Где ты увидел "недотипизированность" или динамическую типизированность? S>Как это? Дак-тайпинг — это и есть "наличие подходящих методов". Вместо точной сигнатуры, как у интерфейсов.
Ага, только разница в том, в какой момент определяется наличие сигнатуры — момент исполнения или компиляции.
V>>VM при загрузке типа будет параметризировать дженерик конкретным типом, все связи будут "бинарные и жесткие". А то с твоих слов выходит, что шаблоны в С++ — это тоже дак-тайпинг, ведь там даже контракты задавать не надо — пихай что хочешь... Хотя мне эти шаблоны помогали имено жестче типизировать абстракции и обкладываться ограничениями. (про С++ разговор особый, как всегда недостающие фичи легко реализуются в нем ср-вами языка, например ограничения шаблонов или контракты... не бинарные интерфейсы, а именно контракты ). S>Совершенно верно, шаблоны в плюсах — это дак-тайпинг. А ты не знал?
Нет не знал и продолжаю не знать.
Шаблоны — это способ описание кодогенерации. А ты не знал?
В генерируемых типах никакого Дак-тайпинга нет и близко!
Понимаешь, там такая штука, в общем, если метода нет, то конкретный тип и не компилируется. Дак-тайпингом было названо несколько другое.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[24]: Философический вопрос про автоматический вывод типов
Здравствуйте, vdimas, Вы писали: V>Метод Class1.M2 разумеется, единственный и неповторимый . Речь же о контракте.
Еще раз попробую тебя нагнуть: что делать, если класс реализует два одноименных метода M2? В дотнете это возможно.
V>2 года назад я слышал подобное о шаблонах в дотнете. И что? Никто не отказался. Реализовали дженерики, и расширили возможности среды.
Нет. Дженерики ничего не выбросили из дотнета. S>>Как это? Дак-тайпинг — это и есть "наличие подходящих методов". Вместо точной сигнатуры, как у интерфейсов. V>Ага, только разница в том, в какой момент определяется наличие сигнатуры — момент исполнения или компиляции.
И? Ты еще не забыл, что инстанцирование дженериков происходит в рантайме? S>>Совершенно верно, шаблоны в плюсах — это дак-тайпинг. А ты не знал? V>Нет не знал и продолжаю не знать. V>Шаблоны — это способ описание кодогенерации. А ты не знал?
Знал. Но от того, что ты назовешь что-то более длинным словом, менее утиной эта типизация не станет. К примеру, шаблону все равно, чем его параметризуют — настоящим указателем на V>В генерируемых типах никакого Дак-тайпинга нет и близко! V>Понимаешь, там такая штука, в общем, если метода нет, то конкретный тип и не компилируется. Дак-тайпингом было названо несколько другое.
Как это несколько другое? Дак тайпинг — это и есть достаточность наличия метода с именем squack для того, чтоб быть уткой. Непринципиально, проверяется это в компайл-тайме или в рантайме. Точнее, нам конечно же удобнее иметь все проверки в компайл-тайме,
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Философический вопрос про автоматический вывод типов
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, vdimas, Вы писали: V>>Метод Class1.M2 разумеется, единственный и неповторимый . Речь же о контракте. S>Еще раз попробую тебя нагнуть: что делать, если класс реализует два одноименных метода M2? В дотнете это возможно.
Один из нас буксует, ИМХО...
В дотнете невозможно напрямую вызвать ни один из этих одноименных метода (вернее, не одноименных, но с одинаковой сигнатурой, ты ведь это хотел спросить?) из класса напрямую, только через приведение к интерфейсу. Я использую эту мысль как демонстрацию неудобства интерфейсов при использовании их как ограничений, а ты зачем-то пытаешься выснить, насколько я хорошо представляю себе технологию реализации интерфейсов в дотнете. Ответ: достаточно, чтобы судить о возможностях дальнейших увеличений удобств в дотнет.
V>>2 года назад я слышал подобное о шаблонах в дотнете. И что? Никто не отказался. Реализовали дженерики, и расширили возможности среды. S>Нет. Дженерики ничего не выбросили из дотнета.
Где я предлагал что-либо выбросить? Я предлагаю добавить. Зачем убирать имеющиеся правила задания ограничений в дженериках?
S>>>Как это? Дак-тайпинг — это и есть "наличие подходящих методов". Вместо точной сигнатуры, как у интерфейсов. V>>Ага, только разница в том, в какой момент определяется наличие сигнатуры — момент исполнения или компиляции. S>И? Ты еще не забыл, что инстанцирование дженериков происходит в рантайме?
Ну вот опять... Ты снова и снова намекаешь на особенности механизма, который реализует VM.Net сейчас? Ты сводишь обсуждение к примерно такому абсурду: "какой смысл обсуждать будущие возможные улучшения, если они не реализуются нынешней реализацией?". Я тебе напоминал про ранние дискуссии о шаблонах в дотнет и точно таких же доводах, но ты не понял намека, очевидно.
Я ведь могу предложить несколько вариантов реализации обсуждаемого механизма и даже относительно форматов PE — где и как оно все будет представляться. РАЗУМЕЕТСЯ, потребуются новые сущности в самой VM.Net, потребуется опять немного расширить объектную систему метаинформации, точно так же как потребовались новые сущности и расширения мета-системы для реализации дженериков. Тебя именно этот факт беспокоит?
S>Как это несколько другое? Дак тайпинг — это и есть достаточность наличия метода с именем squack для того, чтоб быть уткой. Непринципиально, проверяется это в компайл-тайме или в рантайме. Точнее, нам конечно же удобнее иметь все проверки в компайл-тайме
Хорошо, попробую зайти с другой стороны. Давай разделим компайл-тайм и рантайм. Было бы тебе достаточно, чтобы в предлагаемой схеме все несоответствия выявлялись в компайл-тайм? (блин, да ведь даже intellisence сохраняется в этой схеме, в отличие от невозможности применять intellisence к параметрам шаблонов С++)
Мне ведь глубоко фиолетово насчет подробностей внутренних механизмов, если в результате я получу верифицируемое решение, которое не уступает строго-типизированному.