Здравствуйте, _FRED_, Вы писали:
_FR>На самом деле оригинальный вариант так же не редкость (по аналогии с дженерик-методами и методами с тем же именем, но без дженерик-аргументов), но в шарпе это не причиняет неудобств, пока нет вывода типа в вызове конструктора.
Нет никакой разницы и в случае конструкторов. Если кто-то создал специализированную версию (без дженерик-параметров), то он подразумевает, что именно ее нужно предпочесть. Это именно то, что делают компиляторы (всех языков).
Так, в приведенном примере, если не указывать параметры типов, компилятор предпочтет не-дженерик-конструктор, как лучшую перегрузку.
ЗЫ
Я просто удивляюсь, как люди с упорством достойным лучшего применения повторяют глупости которые произносят те, кто просто не хочет делать свою работу качественно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
N>В C# 4.0 наконец-то появился вывод типов из аргументов, которые сами являются method groups. Это позволяет писать всякие хитрые комбинации generic методов, нигде явно не указывая типов-аргументов.
Простите мне мой IQ, но я нифига не понял.
Объясните кто-нибудь в выражениях для чайников.
Ну или приведите пример с указанием что да как сработает.
Спасибо.
Здравствуйте, Kore Sar, Вы писали:
KS>Простите мне мой IQ, но я нифига не понял. KS>Объясните кто-нибудь в выражениях для чайников. KS>Ну или приведите пример с указанием что да как сработает.
Попробую пример чуть попроще привести:
using System;
class Program
{
static void Method<T>(Func<T> action) { }
static int Foo() { return 1; }
static void Main()
{
Method(Foo);
// Error: The type arguments for method 'Program.Method<T>(System.Func<T>)'
// cannot be inferred from the usage. Try specifying the type arguments explicitly.
Method<int>(Foo); // ok
Method(() => 1); //ok
}
}
В наличии generic-метод Method<T>, аргументом которого является делегат Action<T>.
Так как параметр-тип T упоминается в аргументах generic-метода, то компилятор может попробовать вывести тип T в точках вызовов Method().
Что можно передать в качестве Func<T>? Есть два варианта: либо лямбда-выражение, либо выражение "method group".
Method group — это, грубо говоря, один или несколько методов с одинаковым именем (набор из всех перегрузок метода).
В моём примере выражение method group — это упоминание "Foo" в аргументах первых двух вызовов Method().
Так вот, обратите внимание, что первый вызов не скомпилируется если явно не указать тип T.
То есть компилятор не настолько умён в выводе типа T, чтобы обнаружить что в method group "Foo" есть только один метод с сигнатурой int Foo() и других вариантов вывода, кроме как T == int просто не может быть. Зато в случае третьего вызова в примере вывод типов срабатывает — там в качестве делегата методу передано лямбда-выражение.
Так вот, в C# 4.0 вывод типа T более интеллектуален и будет рассматривать выражения method group, а следовательно первый вызов станет компилироваться.
p.s. Это открывает интересные возможности, так как в method group могут находиться несколько методов с различными сигнатурами (включая так же generic-методы) — в этих случаях компилятор будет проводить overload resolution и выводить тип на основании лучшего кандидата на передачу в качестве делегата, что и продемонстрировал в первом посте товарищ nikov (в том примере два кандидата на передачу ConvertAll, выберется generic-версия ConvertToString<T> (другая неприменима) и будет выведен параметр-тип TOutput метода (как string)).
Здравствуйте, Пельмешко, Вы писали:
П>Так вот, в C# 4.0 вывод типа T более интеллектуален и будет рассматривать выражения method group, а следовательно первый вызов станет компилироваться.
Если так дело пойдет, то лет через 10 в шарпе появится полноценный вывод типов внутри тел членов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Это сильно усложнит работу интеграции. Если не ошибаюсь, в одном из комитов я поправил предупреждение. VD>Вывод будет доступен только для параметров имеющих значения по умолчанию.
Что смешного то?
Вывод типов в текущей реализации вещь довольно долгая. А, если у метода не заданы типа аргументов, то придется при малейшем изменении повторно делать вывод типов во всех таких методах.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Я просто удивляюсь, как люди с упорством достойным лучшего применения повторяют глупости которые произносят те, кто просто не хочет делать свою работу качественно.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, VladD2, Вы писали:
VD>>Я просто удивляюсь, как люди с упорством достойным лучшего применения повторяют глупости которые произносят те, кто просто не хочет делать свою работу качественно.
AVK>Ага. Вот, например: Re[7]: C# 4.0 Type Inference
Здравствуйте, AndrewVK, Вы писали:
VD>>Там речь идет о глобальном выводе типов, а тут о мелкой доработке локального.
AVK>Ну да, своя то котомка завсегда тяжелее кажется.
Котомка тут не причем. Есть объективные здравые рассуждения. Сравнивать глобавльный вывод типов с отдельными мелкими фичами локального попросту некорректно.
В указанных тобой сообщениях я говорил о том, что предлагаемый глобальный вывод типов резко усложнить работу интеграции, так как она обрабатывает методы по отдельности (лениво). Тут же идет речь о мелкой доработке компилятора которая вообще не носит принципиального характера. Фактически все аглоритмы для этого уже есть. Нужно только трактовать конструктор как статический метод. В Немерле, к слову, такая трактовка используется изначально, что позволяет ссылаться на конструктры как на любые другие методы, например, передавать их в делегаты.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Котомка тут не причем. Есть объективные здравые рассуждения. Сравнивать глобавльный вывод типов с отдельными мелкими фичами локального попросту некорректно.
Видишь ли, у этой медали есть и оборотная сторона. У вас в Немерлях легаси практически отсутствует, а в случае шарпа это огромные горы кода.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237 on Windows 7 6.1.7100.0>>
Здравствуйте, VladD2, Вы писали:
AVK>>Ну да, своя то котомка завсегда тяжелее кажется.
VD>Котомка тут не причем. Есть объективные здравые рассуждения. Сравнивать глобавльный вывод типов с отдельными мелкими фичами локального попросту некорректно.
Кроме того, каждое изменение в язык, существующий не первый год, и используемый многими программистами, очень рискованно. Есть устрашающие призраки прошлого: "не сломается ли какой-то код из уже написанного?" И есть призраки будущего: "не помешает ли это изменение добавлению еще более полезных фич в язык в дальнейшем?"
А некоторые фичи отсутствуют просто потому, что "no one ever designed, specified, implemented, tested, documented and shipped that feature", как любит говорить Эрик. Просто были другие, более приоритетные задачи.
Здравствуйте, AndrewVK, Вы писали:
AVK>Видишь ли, у этой медали есть и оборотная сторона. У вас в Немерлях легаси практически отсутствует, а в случае шарпа это огромные горы кода.
Причем тут легаси? Никто не предлагает запретить использования явного указания параметров типов.
Просто не хочется лепить их постоянно. Ведь для компилятора не составило бы труда их вывести самостоятельно (если не всегда, то в подновляющем большинстве случаев).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
N>Кроме того, каждое изменение в язык, существующий не первый год, и используемый многими программистами, очень рискованно. Есть устрашающие призраки прошлого: "не сломается ли какой-то код из уже написанного?" И есть призраки будущего: "не помешает ли это изменение добавлению еще более полезных фич в язык в дальнейшем?"э
Дай не будем о третьего лица.
Ты сам то как ответишь на все озвученные тобой вопросы касаемо вывода типов для параметров конструкторов дженерик-типов?
N>А некоторые фичи отсутствуют просто потому, что "no one ever designed, specified, implemented, tested, documented and shipped that feature", как любит говорить Эрик. Просто были другие, более приоритетные задачи.
Опять же, зачем уходить от темы. Кто-то сказал, что фича полезная, но сейчас нет времени? Тут сразу же начали излагать точку зрения, что это в принципе не возможно.
На мой взгляд наличие Nemerle и F# четко показывает, что по крайней мере в рамках тел методов возможен полный вывод типов. А уж его усеченный вариант и подавно, так как он всего лишь частный случай.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Дай не будем о третьего лица. VD>Ты сам то как ответишь на все озвученные тобой вопросы касаемо вывода типов для параметров конструкторов дженерик-типов?
Сходу так не сказать. Нужно читать спецификацию, думать, писать код, пробовать разные варианты. Надо, чтобы кто-то за это платил
Может, что-то поломается.
VD>Опять же, зачем уходить от темы. Кто-то сказал, что фича полезная, но сейчас нет времени? Тут сразу же начали излагать точку зрения, что это в принципе не возможно. VD>На мой взгляд наличие Nemerle и F# четко показывает, что по крайней мере в рамках тел методов возможен полный вывод типов. А уж его усеченный вариант и подавно, так как он всего лишь частный случай.
Кто говорил, что невозможно? Я, например, только говорил, что это задача непростая, особенно если подойти к ней ответственно, думая о пользователях.
Решения в других языках, во-первых, были сделаны в них с самого начала, еще до того как была написана куча кода на предыдущих версиях, а во-вторых не лишены недостатков. В F# используется неуклюжий синтаксис с placeholder'ами, а в Немерле что-то работает, но никто не знает, как это работает, потому что нет спецификации и никто это серьёзно не тестировал.
Здравствуйте, VladD2, Вы писали:
VD>На мой взгляд наличие Nemerle и F# четко показывает, что по крайней мере в рамках тел методов возможен полный вывод типов. А уж его усеченный вариант и подавно, так как он всего лишь частный случай.
Внимание, вопрос. Как должен работать такой код в Nemerle и как он работает на самом деле?
module Program
{
Main() : void
{
def x = A(1);
x.Foo();
}
}
class A
{
public this(_ : long) { }
}
class A[T]
{
public this(_ : T) { }
public Foo() : void { }
}
Здравствуйте, nikov, Вы писали:
N>Немерле что-то работает, но никто не знает, как это работает, потому что нет спецификации и никто это серьёзно не тестировал.
Все работает как описано. Описание есть на сайте. Есть локальный вывод типов который распространяется на весь код внтури членов. А конструкторы трактуются как статические фунции.
И вообще, распространяемые тобой слухи о полном отсутствии спецификации сильно преувеличены. Спецификации нет на АПИ макросов. А на язык она в общем-то есть. Может не такоя полная как у шарпа, но таки она есть. http://nemerle.org/Reference_Manual http://nemerle.org/Quick_Guide
и т.д.
Просто надо понять, что язык по сравнению с шарпом намного меньше. И то что многие ожидают увидиеть в спецификации языка на деле является макросом.
Учитывая, что в области описания типов разница с C# e Nemerle в основном синтаксическая, то пробелы могут спокойно браться из спецификации того самого шарпа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, nikov, Вы писали:
N>Внимание, вопрос. Как должен работать такой код в Nemerle и как он работает на самом деле?
Да, никак не работает, как и должен на самом деле. Ошибку он выдаст, так как Foo нет в А.
А а А он предпочтет по эвристике которая гласит, что если есть функция без дженериков, то она будет более предпочтительной. И связано это не с Foo, а с конструктором А. Именно на нем и отрабатывает это правило.
Теперь ответ по сути. Ты как всегда пытаешься найти граничный случай и показать, мол что есть проблемы.
Но это не проблемы! Если возникнет неоднозначность, то всегда можно явно указать свои намерения:
def x = A.[int](1);
x.Foo();
и все ОК.
На практике, если даже программист не знает о данном правиле, то он напишет код с ошибкой. Получит сообщение о ней. Подведет курсор мыши к переменной "х". Увидит, что он имеет тип без параметров типа и все поймет (если еще не понял по сообщению об ошибке). Далее ему останется только лишь внести указанные мной изменения все будет шоколадно. Ты же пытаешься защитить откровеннийшую лажу, когда вывод типов вроде как есть, но не везде и не доконца, а авторы вместо того, чтобы исправить эту недоработку, распинаются о технических трудностях.
В Шарпе тоже тоже вопросов не будет. Можно ввести правило по которому если есть малешая неоднозначность, то заставлять программиста явно указывать параметры типа. При этом остальные 99.9% случаев будут отлично работать.
Старый код тоже будет работать, так как в нем типы заданы явно.
Так проблема то?
N>
N>module Program
N>{
N> Main() : void
N> {
N> def x = A(1);
N> x.Foo();
N> }
N>}
N>class A
N>{
N> public this(_ : long) { }
N>}
N>class A[T]
N>{
N> public this(_ : T) { }
N> public Foo() : void { }
N>}
N>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD> А конструкторы трактуются как статические фунции.
Ну какой-же он статический метод? Он вполне себе метод экзэмплярный. Да и не конструктор он по сути, инициализатор. Фактически оператор New принимает два параметра — тип объекта, который нужно сконструировать, и инициализатор, который нужно для этого объекта вызвать после его конструирования. И он сначала вызывает код, выделяющий под экзэмпляр память, потом код, превращающий этот кусок памяти в объект. Вот этот код и является конструктором, а уже потом для готового объекта вызывается какой-нибудь инициализатор, с каким-нибудь набором параметров. И сколько-бы ни было у типа так называемых конструкторов, собственно конструирование экзэмпляра производит один и тот-же код. Вот и получается, что так называемый конструктор — самый обыкновенный экзэмплярный метод, единственное отличие — его запрещено вызывать для экзэмпляра более одного раза. Ну и ладно. А вот почему было не разрешить его объявлять виртуальным — загадка.
В шарпе статических методов вообще нет. То, что здесь называется статическим методом, на самом деле является самой обыкновенной регулярной функцией, а класс зачем-то дополнительно нагружен совершенно несвойственной ему функциональностью пространства имён.
Здравствуйте, VladD2, Вы писали:
VD>А а А он предпочтет по эвристике которая гласит, что если есть функция без дженериков, то она будет более предпочтительной. И связано это не с Foo, а с конструктором А. Именно на нем и отрабатывает это правило.
А вот C# выберет конструктор с дженериком (если это будет реализовано).
Здравствуйте, Мизантроп, Вы писали:
VD>> А конструкторы трактуются как статические фунции.
М>Ну какой-же он статический метод?
Просто, какое-то "Горе от ума".
К сожалению, знание внутрепних аспектов реализации никак не подталеивает к абстрактному машлению. Даже наоборот мешаютему.
И все же попробуй абстрагироваться. Забудь на минуточку о том что ты знаешь о внутреннем устройстве CLR и попробуй подумать о том как можно варазить создание обекта (для программиста, а не для CLR).
Так вот конструктор можно представит банальной функцией получаюжей нолили более аргументов и создающей объект определенного типа.
Паттерн "Фабричный метод" пользуется таким представлением дляя инкапсуляции логики создания объекта.
Так почему же нельзя рассматривать и обычные конструктораы подобным образом?
Вот Nemerle и поступает подобным образом.
Что же это дает?
Оказывается весьма не мало.
1. Это позволяет обращаться с конструкторами как с обычными функциями (передавать их в качестве параметра, помещать в переменные, формировать на их основе другие функции). Другими словами рассмитривать конструктор как первоклассную сущность языка.
2. Упростит концепции (правила) языка и реализацию компилятора. Ведь для конструкторов становятся применимы все павила применимые к обычным функциям.
3. (пожалуй самое важное в контексте данной темы) Становится ясно, что к констукторам можно без проблем применять все правила вывода типов применимые к обычным функциям.
На лицо унификация одновременно упрощающая восприятме, использование и реализаци.
Теперь, что касается статических методов и свободных фенкций. Формально вдотнете нет свободных функций. И вообще — это терминология C++. Однако можно просто считатические методы и свободные функции синонимами так как если абстрагироваться от деталей, классы для статических методов скорее служат для целей выделения пространств имен/модулей. Так что по фигу как их называть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.