C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.09.09 11:35
Оценка: 70 (9)
В C# 4.0 наконец-то появился вывод типов из аргументов, которые сами являются method groups. Это позволяет писать всякие хитрые комбинации generic методов, нигде явно не указывая типов-аргументов.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var y = new List<int> {1, 2, 3};
        var z = y.ConvertAll(ConvertToString);
    }

    static string ConvertToString<T>(T x)
    {
        return x.ToString();
    }

    static string ConvertToString(Guid x)
    {
        return x.ToString("N");
    }
}
Re: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.09.09 13:01
Оценка: 1 (1) +3
Здравствуйте, nikov, Вы писали:

N>В C# 4.0 наконец-то появился вывод типов из аргументов, которые сами являются method groups. Это позволяет писать всякие хитрые комбинации generic методов, нигде явно не указывая типов-аргументов.


А что они вывод типов для конструкторов то не сделают?
Кривотень ведь еще та.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.09.09 13:31
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А что они вывод типов для конструкторов то не сделают?

VD>Кривотень ведь еще та.

Увы. Даже не слышал, чтобы такое планировалось.
Re: C# 4.0 Type Inference
От: Алексей.  
Дата: 02.09.09 13:51
Оценка:
Здравствуйте, nikov, Вы писали:

N>В C# 4.0 наконец-то появился вывод типов из аргументов, которые сами являются method groups. Это позволяет писать всякие хитрые комбинации generic методов, нигде явно не указывая типов-аргументов.


Где можно прочитать описание как это работает/должно работать?

Раньше компилятор не позволял такого https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=299065
Re: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.09.09 13:54
Оценка:
Кстати, есть еще одно интересное изменение в спецификации насчет Fixing'а.

Новый вариант:

• We then examine each bound for Xi in turn: For each exact bound U of Xi all types Uj which are not identical to U are removed from the candidate set. For each lower bound U of Xi all types Uj to which there is not an implicit conversion from U are removed from the candidate set. For each upper bound U of Xi all types Uj from which there is not an implicit conversion to U are removed from the candidate set.


Заметьте, что здесь говорится о необходимости implicit conversion, в то время как старый вариант говорил о standard implicit conversion (более узкое множество). На самом деле компилятор и в предыдущей версии работал, как будто речь идет обо всех implicit conversion — разработчики компилятора забыли передать нужный флаг, а я заметил это уже после релиза. Теперь решили привести спецификацию в согласованное состояние с реализацией.
Re[2]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.09.09 14:04
Оценка: 4 (1)
Здравствуйте, Алексей., Вы писали:

А>Где можно прочитать описание как это работает/должно работать?

А>Раньше компилятор не позволял такого https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=299065

На самом деле сейчас всё сделали, как и было написано в разделе 7.4.2.6 Output type inferences ещё в спецификации C# 3.0. Overload resolution вполне можно произвести, когда все типы аргументов заданы изначально или выведены ранее. То, что написано на коннекте выглядит просто как не очень серьёзное оправдание.
Re[3]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.09.09 14:57
Оценка:
Здравствуйте, nikov, Вы писали:

VD>>А что они вывод типов для конструкторов то не сделают?

VD>>Кривотень ведь еще та.

N>Увы. Даже не слышал, чтобы такое планировалось.


Я тоже. Вообще, не ясно, они там совсем от народа оторвались? Ведь принципиальных проблем с эти не должно быть. Их не не полноценный вывод типов просят сделать, а практически то, что уже есть. Ведь фабричные методы выводятся на раз.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.09.09 15:08
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Ну не совсем то. Классы можно перегружать по количеству типов-параметров. Если мы позволим опускать типы-аргументы при выводе, то множество конструкторов-кандидатов придется собирать из разных, никак не связанных, типов.

Возникает и много других вопросов. А если конструктор вызван с object/collection initializer (как List в моем примере), то учитывать ли типы выражений в этом инициализаторе для вывода типов-аргументов создаваемого класса? А ведь это могут быть аргументы для нескольких разных методов Add, которые в свою очередь могут быть generic. А учитывать ли иницициализаторы для вложенных объектов? И т.д. и т.п. В общем, нетривиальная задача.
Re[5]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.09.09 15:18
Оценка:
Здравствуйте, nikov, Вы писали:

N>Ну не совсем то. Классы можно перегружать по количеству типов-параметров. Если мы позволим опускать типы-аргументы при выводе, то множество конструкторов-кандидатов придется собирать из разных, никак не связанных, типов.


N>Возникает и много других вопросов. А если конструктор вызван с object/collection initializer (как List в моем примере), то учитывать ли типы выражений в этом инициализаторе для вывода типов-аргументов создаваемого класса? А ведь это могут быть аргументы для нескольких разных методов Add, которые в свою очередь могут быть generic. А учитывать ли иницициализаторы для вложенных объектов? И т.д. и т.п. В общем, нетривиальная задача.


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

Еще раз повторюсь, что раз фабричные методы прокатывают, то и конструктор можно рассматривать как такой фабричный метод.

Погляди на кортежи из .NET 4.0. Методы Create() — это же форменные костыли.
Я бы со стыда сгорел от такой халтуры.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.09.09 15:26
Оценка:
Здравствуйте, VladD2, Вы писали:

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

VD>А на практике, в случаях неоднозначности можно выдавать сообщения об ошибках. А 99% кода будет работать как надо.

Да я, в общем-то, не возражаю. Пусть сделают.
А когда в Nemerle появится вывод сигнатуры для приватных методов класса? А то всё пишет, что not yet implemented, мол.
Re[5]: C# 4.0 Type Inference
От: Пельмешко Россия blog
Дата: 02.09.09 15:53
Оценка: 12 (1)
Здравствуйте, nikov, Вы писали:

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


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


N>Ну не совсем то. Классы можно перегружать по количеству типов-параметров. Если мы позволим опускать типы-аргументы при выводе, то множество конструкторов-кандидатов придется собирать из разных, никак не связанных, типов.


Этого ни в коем случае допускать нельзя, можно же просто ввести синтаксис для различия generic overloads:
var dict = new Dictionary<,> {
    { 1, "abc" },
    { 2, "def" }
};
Другое дело в том, насколько это будет непонятно
Получается что "Dictionary<,>" будет иметь сильно разный смысл в зависимости от контекста: в typeof() и new expression...

N>Возникает и много других вопросов. А если конструктор вызван с object/collection initializer (как List в моем примере), то учитывать ли типы выражений в этом инициализаторе для вывода типов-аргументов создаваемого класса? А ведь это могут быть аргументы для нескольких разных методов Add, которые в свою очередь могут быть generic. А учитывать ли иницициализаторы для вложенных объектов? И т.д. и т.п. В общем, нетривиальная задача.


А вот это пипец..
Re[7]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.09.09 16:34
Оценка: :)
Здравствуйте, nikov, Вы писали:

N>Да я, в общем-то, не возражаю. Пусть сделают.

N>А когда в Nemerle появится вывод сигнатуры для приватных методов класса? А то всё пишет, что not yet implemented, мол.

Это сильно усложнит работу интеграции. Если не ошибаюсь, в одном из комитов я поправил предупреждение.
Вывод будет доступен только для параметров имеющих значения по умолчанию.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.09.09 16:38
Оценка:
Здравствуйте, Пельмешко, Вы писали:

N>>Ну не совсем то. Классы можно перегружать по количеству типов-параметров. Если мы позволим опускать типы-аргументы при выводе, то множество конструкторов-кандидатов придется собирать из разных, никак не связанных, типов.


П>Этого ни в коем случае допускать нельзя, можно же просто ввести синтаксис для различия generic overloads:

П>
П>var dict = new Dictionary<,> {
П>    { 1, "abc" },
П>    { 2, "def" }
П>};
П>
Другое дело в том, насколько это будет непонятно

П>Получается что "Dictionary<,>" будет иметь сильно разный смысл в зависимости от контекста: в typeof() и new expression...

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

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

N>>Возникает и много других вопросов. А если конструктор вызван с object/collection initializer (как List в моем примере), то учитывать ли типы выражений в этом инициализаторе для вывода типов-аргументов создаваемого класса? А ведь это могут быть аргументы для нескольких разных методов Add, которые в свою очередь могут быть generic. А учитывать ли иницициализаторы для вложенных объектов? И т.д. и т.п. В общем, нетривиальная задача.


П>А вот это пипец..


Если алгоритм вывода типов грамотный, то все будет ОК. Для шарпа можно тупо ругаться на не однозначные (с его точки зрения) случаи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: C# 4.0 Type Inference
От: Пельмешко Россия blog
Дата: 02.09.09 18:14
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Пельмешко, Вы писали:


N>>>Ну не совсем то. Классы можно перегружать по количеству типов-параметров. Если мы позволим опускать типы-аргументы при выводе, то множество конструкторов-кандидатов придется собирать из разных, никак не связанных, типов.


П>>Этого ни в коем случае допускать нельзя, можно же просто ввести синтаксис для различия generic overloads:

П>>
П>>var dict = new Dictionary<,> {
П>>    { 1, "abc" },
П>>    { 2, "def" }
П>>};
П>>
Другое дело в том, насколько это будет непонятно

П>>Получается что "Dictionary<,>" будет иметь сильно разный смысл в зависимости от контекста: в typeof() и new expression...

VD>Не нужно ничего подобного делать. Если параметры типа не выводятся по простому, то можно просто попросить программиста задать их явно.


Интересно, почему тогда в F# приходится использовать placeholder чтобы руками указать, что создавать будем?
let foo =
    let d = new Dictionary<_,_>()
    d.Add(1, "abc")
    d.Add(2, "def")
    d

Мне всё же кажется, что это неспроста
Re[8]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.09.09 14:05
Оценка: 14 (2)
Здравствуйте, Пельмешко, Вы писали:

П>Интересно, почему тогда в F# приходится использовать placeholder чтобы руками указать, что создавать будем?

П>
П>let foo =
П>    let d = new Dictionary<_,_>()
П>    d.Add(1, "abc")
П>    d.Add(2, "def")
П>    d
П>

П>Мне всё же кажется, что это неспроста

Я не уверен, что ты вообще прав. Но если это так, то это вопрос к его разработчику и тем кто хочет протолкнуть в массы такой язык. В Nemerle никакихъ проблем с этим нет:
using System.Collections.Generic;
using System.Console;

module Program
{
  Main() : void
  {
    def d = Dictionary();

    d.Add(1, "abc");
    d.Add(2, "def");

    foreach (x in d)
      WriteLine($"$(x.Key)=$(x.Value)");
  }
}

Более того работает автодополнение при воводе, хинты и т.п. (в IDE).

Вот если будут неоднозначности, то надо будет или плэйсхолдеры задать (как в F#-примере) или даже реальные типы. В прочем, вероятность того, что такая неоднозночность возникнет, на практике, весьма мала. Так что это не более чем теоритические рассуждения цель которых отмазаться от сложной работы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: C# 4.0 Type Inference
От: Пельмешко Россия blog
Дата: 04.09.09 11:12
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я не уверен, что ты вообще прав.


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

Влад, я вот с нескольких попыток так и не смог заставить немерль создать всё же generic-версию Foo:
class Foo
{
  public this(a : int) { }
}

class Foo[T]
{
  public this(a : T) { }
}

module Program
{
  Main() : void
  {
    def x = Foo(5);
  }
}


Я думал, что должно быть что-то типа:
    def x = Foo(5) : Foo[int];

Но компилятор не разделяет моего мнения
Re[10]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.09.09 13:16
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Влад, я вот с нескольких попыток так и не смог заставить немерль создать всё же generic-версию Foo:

П>
П>class Foo
П>{
П>  public this(a : int) { }
П>}

П>class Foo[T]
П>{
П>  public this(a : T) { }
П>}

П>module Program
П>{
П>  Main() : void
П>  {
П>    def x = Foo(5);
П>  }
П>}
П>


Вот это как раз конфликт в котором требеуется явно указать аргументы типа:
def x = Foo.[int](5);

Или так:
def x = Foo.[_](5);

так как типы отличаются по количеству параметров типа.

Но на практике такого я не встречал. Типы создаются для конкретных нужд и эти нужды сами определяют разичия между ними.

Что же касается конфликтов, то их хватает и в C#. Замени типы на дженерик-методы и получишь ту же картину.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: C# 4.0 Type Inference
От: _FRED_ Черногория
Дата: 04.09.09 13:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Но на практике такого я не встречал. Типы создаются для конкретных нужд и эти нужды сами определяют разичия между ними.


Например, таплы обычно различают по количеству элементов. Можно, конечно же количество добавляь к имени класса Tuple2<,>; Tuple3<,,> но просто Tuple<,>; Tuple<,,> ИМХО, эстетичнее.
Help will always be given at Hogwarts to those who ask for it.
Re[12]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.09.09 14:08
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Например, таплы обычно различают по количеству элементов. Можно, конечно же количество добавляь к имени класса Tuple2<,>; Tuple3<,,> но просто Tuple<,>; Tuple<,,> ИМХО, эстетичнее.


С кортежами никогда никаких проблем не было. У них разные списки параметров типов. В примере приведенно выше было намеренно смоделирована ситуация когда есть два типа конфликтующих при выводе (с типом и такой же без него). У кортежей же всегда разное количество параметров типов которые всегда определяются конструктором.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: C# 4.0 Type Inference
От: _FRED_ Черногория
Дата: 04.09.09 14:19
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Например, таплы обычно различают по количеству элементов. Можно, конечно же количество добавляь к имени класса Tuple2<,>; Tuple3<,,> но просто Tuple<,>; Tuple<,,> ИМХО, эстетичнее.


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


Ах да, точно

На самом деле оригинальный вариант так же не редкость (по аналогии с дженерик-методами и методами с тем же именем, но без дженерик-аргументов), но в шарпе это не причиняет неудобств, пока нет вывода типа в вызове конструктора.
Help will always be given at Hogwarts to those who ask for it.
Re[14]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.09.09 14:30
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>На самом деле оригинальный вариант так же не редкость (по аналогии с дженерик-методами и методами с тем же именем, но без дженерик-аргументов), но в шарпе это не причиняет неудобств, пока нет вывода типа в вызове конструктора.


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

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

ЗЫ

Я просто удивляюсь, как люди с упорством достойным лучшего применения повторяют глупости которые произносят те, кто просто не хочет делать свою работу качественно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: C# 4.0 Type Inference
От: Kore Sar  
Дата: 06.09.09 10:20
Оценка: +1
Здравствуйте, nikov, Вы писали:

N>В C# 4.0 наконец-то появился вывод типов из аргументов, которые сами являются method groups. Это позволяет писать всякие хитрые комбинации generic методов, нигде явно не указывая типов-аргументов.


Простите мне мой IQ, но я нифига не понял.
Объясните кто-нибудь в выражениях для чайников.
Ну или приведите пример с указанием что да как сработает.
Спасибо.
Re[2]: C# 4.0 Type Inference
От: Пельмешко Россия blog
Дата: 06.09.09 18:17
Оценка: 31 (4)
Здравствуйте, 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)).

p.s.s. Надеюсь адекватно получилось разъяснить...
Re[3]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.09.09 14:01
Оценка: +1 :)
Здравствуйте, Пельмешко, Вы писали:

П>Так вот, в C# 4.0 вывод типа T более интеллектуален и будет рассматривать выражения method group, а следовательно первый вызов станет компилироваться.


Если так дело пойдет, то лет через 10 в шарпе появится полноценный вывод типов внутри тел членов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.09.09 15:57
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Это сильно усложнит работу интеграции. Если не ошибаюсь, в одном из комитов я поправил предупреждение.

VD>Вывод будет доступен только для параметров имеющих значения по умолчанию.

Что смешного то?
Вывод типов в текущей реализации вещь довольно долгая. А, если у метода не заданы типа аргументов, то придется при малейшем изменении повторно делать вывод типов во всех таких методах.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: C# 4.0 Type Inference
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 08.09.09 09:15
Оценка: +1 :)
Здравствуйте, VladD2, Вы писали:

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


Ага. Вот, например: Re[7]: C# 4.0 Type Inference
Автор: VladD2
Дата: 02.09.09

... << RSDN@Home 1.2.0 alpha 4 rev. 1237 on Windows 7 6.1.7100.0>>
AVK Blog
Re[16]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.09.09 19:40
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


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


AVK>Ага. Вот, например: Re[7]: C# 4.0 Type Inference
Автор: VladD2
Дата: 02.09.09

AVK>

Если бы не знал тебя лично, подумал бы что общаясь с полным дилетантом.
Там речь идет о глобальном выводе типов, а тут о мелкой доработке локального.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: C# 4.0 Type Inference
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 09.09.09 21:01
Оценка: +1 -1
Здравствуйте, VladD2, Вы писали:

VD>Там речь идет о глобальном выводе типов, а тут о мелкой доработке локального.


Ну да, своя то котомка завсегда тяжелее кажется.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237 on Windows 7 6.1.7100.0>>
AVK Blog
Re[18]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.09.09 13:58
Оценка:
Здравствуйте, AndrewVK, Вы писали:

VD>>Там речь идет о глобальном выводе типов, а тут о мелкой доработке локального.


AVK>Ну да, своя то котомка завсегда тяжелее кажется.


Котомка тут не причем. Есть объективные здравые рассуждения. Сравнивать глобавльный вывод типов с отдельными мелкими фичами локального попросту некорректно.

В указанных тобой сообщениях я говорил о том, что предлагаемый глобальный вывод типов резко усложнить работу интеграции, так как она обрабатывает методы по отдельности (лениво). Тут же идет речь о мелкой доработке компилятора которая вообще не носит принципиального характера. Фактически все аглоритмы для этого уже есть. Нужно только трактовать конструктор как статический метод. В Немерле, к слову, такая трактовка используется изначально, что позволяет ссылаться на конструктры как на любые другие методы, например, передавать их в делегаты.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[19]: C# 4.0 Type Inference
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.09.09 16:23
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Видишь ли, у этой медали есть и оборотная сторона. У вас в Немерлях легаси практически отсутствует, а в случае шарпа это огромные горы кода.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237 on Windows 7 6.1.7100.0>>
AVK Blog
Re[19]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.09.09 16:41
Оценка:
Здравствуйте, VladD2, Вы писали:

AVK>>Ну да, своя то котомка завсегда тяжелее кажется.


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


Не всё так просто, как может показаться на первый взгляд. Почитай How many Microsoft employees does it take to change a lightbulb?

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

А некоторые фичи отсутствуют просто потому, что "no one ever designed, specified, implemented, tested, documented and shipped that feature", как любит говорить Эрик. Просто были другие, более приоритетные задачи.
Re[20]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.09.09 17:31
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


Причем тут легаси? Никто не предлагает запретить использования явного указания параметров типов.
Просто не хочется лепить их постоянно. Ведь для компилятора не составило бы труда их вывести самостоятельно (если не всегда, то в подновляющем большинстве случаев).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.09.09 17:42
Оценка:
Здравствуйте, nikov, Вы писали:

N>Кроме того, каждое изменение в язык, существующий не первый год, и используемый многими программистами, очень рискованно. Есть устрашающие призраки прошлого: "не сломается ли какой-то код из уже написанного?" И есть призраки будущего: "не помешает ли это изменение добавлению еще более полезных фич в язык в дальнейшем?"э


Дай не будем о третьего лица.
Ты сам то как ответишь на все озвученные тобой вопросы касаемо вывода типов для параметров конструкторов дженерик-типов?

N>А некоторые фичи отсутствуют просто потому, что "no one ever designed, specified, implemented, tested, documented and shipped that feature", как любит говорить Эрик. Просто были другие, более приоритетные задачи.


Опять же, зачем уходить от темы. Кто-то сказал, что фича полезная, но сейчас нет времени? Тут сразу же начали излагать точку зрения, что это в принципе не возможно.
На мой взгляд наличие Nemerle и F# четко показывает, что по крайней мере в рамках тел методов возможен полный вывод типов. А уж его усеченный вариант и подавно, так как он всего лишь частный случай.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[21]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.09.09 18:17
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Дай не будем о третьего лица.

VD>Ты сам то как ответишь на все озвученные тобой вопросы касаемо вывода типов для параметров конструкторов дженерик-типов?

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

VD>Опять же, зачем уходить от темы. Кто-то сказал, что фича полезная, но сейчас нет времени? Тут сразу же начали излагать точку зрения, что это в принципе не возможно.

VD>На мой взгляд наличие Nemerle и F# четко показывает, что по крайней мере в рамках тел методов возможен полный вывод типов. А уж его усеченный вариант и подавно, так как он всего лишь частный случай.

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

Решения в других языках, во-первых, были сделаны в них с самого начала, еще до того как была написана куча кода на предыдущих версиях, а во-вторых не лишены недостатков. В F# используется неуклюжий синтаксис с placeholder'ами, а в Немерле что-то работает, но никто не знает, как это работает, потому что нет спецификации и никто это серьёзно не тестировал.
Re[21]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.09.09 18:42
Оценка:
Здравствуйте, 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 { }
}
Re[22]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.09.09 20:53
Оценка:
Здравствуйте, nikov, Вы писали:

N>Немерле что-то работает, но никто не знает, как это работает, потому что нет спецификации и никто это серьёзно не тестировал.


Все работает как описано. Описание есть на сайте. Есть локальный вывод типов который распространяется на весь код внтури членов. А конструкторы трактуются как статические фунции.

И вообще, распространяемые тобой слухи о полном отсутствии спецификации сильно преувеличены. Спецификации нет на АПИ макросов. А на язык она в общем-то есть. Может не такоя полная как у шарпа, но таки она есть.
http://nemerle.org/Reference_Manual
http://nemerle.org/Quick_Guide
и т.д.

Просто надо понять, что язык по сравнению с шарпом намного меньше. И то что многие ожидают увидиеть в спецификации языка на деле является макросом.
Учитывая, что в области описания типов разница с C# e Nemerle в основном синтаксическая, то пробелы могут спокойно браться из спецификации того самого шарпа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[22]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.09.09 21:06
Оценка:
Здравствуйте, 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>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[23]: C# 4.0 Type Inference
От: Мизантроп  
Дата: 11.09.09 03:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD> А конструкторы трактуются как статические фунции.


Ну какой-же он статический метод? Он вполне себе метод экзэмплярный. Да и не конструктор он по сути, инициализатор. Фактически оператор New принимает два параметра — тип объекта, который нужно сконструировать, и инициализатор, который нужно для этого объекта вызвать после его конструирования. И он сначала вызывает код, выделяющий под экзэмпляр память, потом код, превращающий этот кусок памяти в объект. Вот этот код и является конструктором, а уже потом для готового объекта вызывается какой-нибудь инициализатор, с каким-нибудь набором параметров. И сколько-бы ни было у типа так называемых конструкторов, собственно конструирование экзэмпляра производит один и тот-же код. Вот и получается, что так называемый конструктор — самый обыкновенный экзэмплярный метод, единственное отличие — его запрещено вызывать для экзэмпляра более одного раза. Ну и ладно. А вот почему было не разрешить его объявлять виртуальным — загадка.

В шарпе статических методов вообще нет. То, что здесь называется статическим методом, на самом деле является самой обыкновенной регулярной функцией, а класс зачем-то дополнительно нагружен совершенно несвойственной ему функциональностью пространства имён.
"Нормальные герои всегда идут в обход!"
Re[23]: C# 4.0 Type Inference
От: Алексей.  
Дата: 11.09.09 06:38
Оценка:
Здравствуйте, VladD2, Вы писали:

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


А вот C# выберет конструктор с дженериком (если это будет реализовано).
Re[24]: AdvancedHints Beta
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 08:51
Оценка: 4 (1) +1
Здравствуйте, Мизантроп, Вы писали:

VD>> А конструкторы трактуются как статические фунции.


М>Ну какой-же он статический метод?


Просто, какое-то "Горе от ума".
К сожалению, знание внутрепних аспектов реализации никак не подталеивает к абстрактному машлению. Даже наоборот мешаютему.
И все же попробуй абстрагироваться. Забудь на минуточку о том что ты знаешь о внутреннем устройстве CLR и попробуй подумать о том как можно варазить создание обекта (для программиста, а не для CLR).
Так вот конструктор можно представит банальной функцией получаюжей нолили более аргументов и создающей объект определенного типа.

Паттерн "Фабричный метод" пользуется таким представлением дляя инкапсуляции логики создания объекта.
Так почему же нельзя рассматривать и обычные конструктораы подобным образом?

Вот Nemerle и поступает подобным образом.

Что же это дает?

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

На лицо унификация одновременно упрощающая восприятме, использование и реализаци.

Теперь, что касается статических методов и свободных фенкций. Формально вдотнете нет свободных функций. И вообще — это терминология C++. Однако можно просто считатические методы и свободные функции синонимами так как если абстрагироваться от деталей, классы для статических методов скорее служат для целей выделения пространств имен/модулей. Так что по фигу как их называть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[24]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 09:00
Оценка:
Здравствуйте, Алексей., Вы писали:

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


А>А вот C# выберет конструктор с дженериком (если это будет реализовано).


На сегодня, C# просто ничего не выбрет так как для конструкторов он требует задавать параметтры типов.
если же говорит огипотетическом будущем, то конечно же эвристика "предпочтение" не дженерик-метода — это особенность Nemerle. На мой взгляд это очень удачная эвристика. но авторам C#-а кикто и ни что не мешает использовать другой подход. В общем, в еашем случае эта эвристика не имеет ровным счетом ни какого значения.
Главное, что нет разумных причин чтобы запрещать вывод типов для конструкторов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[23]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 11.09.09 09:13
Оценка:
Здравствуйте, VladD2, Вы писали:

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


N>>Внимание, вопрос. Как должен работать такой код в Nemerle и как он работает на самом деле?


VD>Да, никак не работает, как и должен на самом деле. Ошибку он выдаст, так как Foo нет в А.

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

1) А где это правило написано? Ты говорил, что если правило нигде не написано, то нужно брать соответствующее правило из спеки C#. А в C# overload resolution производится после вывода типов-аргументов и их подстановки в сигнатуру. После этого мы имеем сигнатуры A(long) и A(int), и последняя, естественно лучше, так как есть точное совпадение типов.

2) Хорошо, допустим, в Немерле другое правило. Почему после замены A(long) на A(long?) код начинает компилироваться и выбирается generic тип?

3) А как же пресловутый вывод типов из использования? Я ожидал, что компилятор будет рассуждать так: У нас есть два конструктора. Но постом у сконструированного объекта вызывется метод Foo. Ага, такой метод есть только у generic типа. Значит, его конструктор мы и вызываем. Я неправильно понял идею вывода из использования?
Re[24]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 10:34
Оценка:
Здравствуйте, nikov, Вы писали:

N>1) А где это правило написано? Ты говорил, что если правило нигде не написано, то нужно брать соответствующее правило из спеки C#. А в C# overload resolution производится после вывода типов-аргументов и их подстановки в сигнатуру. После этого мы имеем сигнатуры A(long) и A(int), и последняя, естественно лучше, так как есть точное совпадение типов.


Гдето я видел его описание, но не там где следовал бы.
Согласен, что разрешение перегрузки стоило бы описать по четче.

Что до точного совпадения, то это тонкий вопрос и я не готов на него сейчас ответить.
Там играет роль констант-фолдинг и кое что другое.

N>2) Хорошо, допустим, в Немерле другое правило. Почему после замены A(long) на A(long?) код начинает компилироваться и выбирается generic тип?


Можно пример?

N>3) А как же пресловутый вывод типов из использования? Я ожидал, что компилятор будет рассуждать так: У нас есть два конструктора. Но постом у сконструированного объекта вызывется метод Foo. Ага, такой метод есть только у generic типа. Значит, его конструктор мы и вызываем. Я неправильно понял идею вывода из использования?


Дык вывод идет из первого использования. Сначала выводится конструктор, а уже на основании типа конструтора определяется тип переменной и производится разрешение перегрузки.
Вообще там все очень не просто. Вывод типов — подразумевает построение графа завмостей между всеми типами используемыми в методе.
Но в шарпе такого нет. Так что даже не стоит об этом говорить. Но это как раз упрощает ситуцию. Вывод типов конструкторов может делаться по тем же принципам, что и статических методоа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[25]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 11.09.09 10:42
Оценка:
Здравствуйте, VladD2, Вы писали:

N>>2) Хорошо, допустим, в Немерле другое правило. Почему после замены A(long) на A(long?) код начинает компилироваться и выбирается generic тип?


VD>Можно пример?


module Program
{
  Main() : void
  {
    def x = A(1);
    x.Foo();
  }
}

class A
{
    public this(_ : long?) { } // Поменяли 'long' на 'long?'
}

class A[T]
{
    public this(_ : T) { }
    public Foo() : void { }
}
Re[25]: AdvancedHints Beta
От: Мизантроп  
Дата: 11.09.09 11:24
Оценка:
Здравствуйте, VladD2, Вы писали:

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


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

VD>Так вот конструктор можно представит банальной функцией получаюжей нолили более аргументов и создающей объект определенного типа.


VD>Паттерн "Фабричный метод" пользуется таким представлением дляя инкапсуляции логики создания объекта.

VD>Так почему же нельзя рассматривать и обычные конструктораы подобным образом?

VD>Вот Nemerle и поступает подобным образом.


VD>Что же это дает?


VD>Оказывается весьма не мало.

VD>1. Это позволяет обращаться с конструкторами как с обычными функциями (передавать их в качестве параметра, помещать в переменные, формировать на их основе другие функции). Другими словами рассмитривать конструктор как первоклассную сущность языка.
VD>2. Упростит концепции (правила) языка и реализацию компилятора. Ведь для конструкторов становятся применимы все павила применимые к обычным функциям.
VD>3. (пожалуй самое важное в контексте данной темы) Становится ясно, что к констукторам можно без проблем применять все правила вывода типов применимые к обычным функциям.

VD>На лицо унификация одновременно упрощающая восприятме, использование и реализаци.


Так ведь я вроде и не предлагал рассматривать конструктор как нечто особенное, разве нет?
Всё это замечательно, за исключением одного — зачем использовать для этого передачу конструктора, когда то-же самое, и даже большее можно получить, передавая ссылку на RTTI — при условии, что язык позволяет использовать RTTI для создания экэмпляров.

VD>Теперь, что касается статических методов и свободных фенкций. Формально вдотнете нет свободных функций. И вообще — это терминология C++. Однако можно просто считатические методы и свободные функции синонимами так как если абстрагироваться от деталей, классы для статических методов скорее служат для целей выделения пространств имен/модулей. Так что по фигу как их называть.


"Не плоди сущности без необходимости". Экзэмплярный метод должен иметь (и имеет) полный доступ к экзэмпляру, с учётом ограничений видимости. Классовый метод должен иметь полный доступ, с теми-же ограничениями, к информации класса, к его RTTI. А если это свободная функция, то она ею должна быть. А если это класс, то он и должен быть классом, а не пространством имён. Но всё это моё чистое IMHO, без претензий на высшую истину.

VD>Просто, какое-то "Горе от ума".


Извините, что сдуру вмешался в вашу высоинтеллектуальную дискуссию.
"Нормальные герои всегда идут в обход!"
Re[26]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 11:48
Оценка:
Здравствуйте, nikov, Вы писали:
N>>>2) Хорошо, допустим, в Немерле другое правило. Почему после замены A(long) на A(long?) код начинает компилироваться и выбирается generic тип?

VD>>Можно пример?


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?) { } // Поменяли 'long' на 'long?'
N>}

N>class A[T]
N>{
N>    public this(_ : T) { }
N>    public Foo() : void { }
N>}
N>


Потому, что ncc (незнаю с какого переполоху) не считает возможным привести int к Nullable<long>. Это хорошо видно если удалить класс A[T] или поменять константу "1" на "1L".
В первом случае компилятор заорет:
Error: in argument #1 (_N_wildcard_2658), needed a System.Nullable[long], got int: System.Int32 is not a subtype of System.Nullable.[T] [simple require]

Во втором:
Main.n(10,5):Error: there is no member named 'Foo' in A with type ?
Main.n(10,5):Error: unbound name 'Foo' in 'x'

т.е. все вернется на круги своя.

Так что если это и баг, то в другом месте.
К рассматриваемому вопросу вывода типов конструкторов это отношения не имеет.

ЗЫ

Боюсь, что проблемы МС банально смешны. Ребята просто не додумались посмотреть на конструктор как на статическую функцию. Они рассматривают конструктор как уникальную сущность. Отсюда и проблемы.
А может они уже просто зашились в коде компилятора написанном на С++ и любое изменение дается настолько болезненно, что проще отбрехаться нежели что-то переделать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[27]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 11.09.09 11:57
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Так что если это и баг, то в другом месте.

VD>К рассматриваемому вопросу вывода типов конструкторов это отношения не имеет.

Тем не менее это показывает, что в компиляторе C# предпочитают выделять ресурсы на то, чтобы поддерживать уровень багов на низком уровне, чем на добавление множества новых фич. Немерле — это экспериментальный язык, и он может позволить себе гораздо больше новых фич (разумеется, ценой уменьшения качества, стабильности и скорости компиляции). Наиболее полезные фичи рано или поздно перекочуют в мейнстримовые языки (после написания документации, шлифовки и тщательного тестирования).
Re[26]: AdvancedHints Beta
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 12:39
Оценка: -1
Здравствуйте, Мизантроп, Вы писали:

М>Ну что Вы, я весьма слабо знаю внутреннюю кухню. CLR. Зато достаточно неплохо представляю способы, какими подобные вещи реализуются. Но призыв "абстрагироваться от внутренней кухни", на мой взгляд, выглядит несколько странно при обсуждении, почему то или иное поведение не реализовано в той самой внутренней кухне.


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

М>Так ведь я вроде и не предлагал рассматривать конструктор как нечто особенное, разве нет?


Ты предлагал не рассматривать его как ординарную функцию. А как раз это решает тучу проблем.

М>Всё это замечательно, за исключением одного — зачем использовать для этого передачу конструктора, когда то-же самое, и даже большее можно получить, передавая ссылку на RTTI — при условии, что язык позволяет использовать RTTI для создания экэмпляров.


Э... Однобокий у тебя взгляд какой-то. Просто таки просвечивает С++.
Какой RTTI? (кстати в дотнете это называется рефлексия)
Зачем оно тут?
Мы ведь о языках говорим, а не о их рантаймах.

Нам нужно удобно и просто работать с конструкторами. Конечно на конструктор можно смотреть как угодно. Можно думать о нем как об инмперативной конструкции меняющей биты у объекта. Еще можно вести речь о каких то там операторах new которые выделяют память и вызвают этот императивный метод. Конечно можно! Но нужно ли?
У нас есть задача — создать объект имея некоторую входную информацию. Функция справится с этой задачей на ура. При этом мы можем мыслить о создании объекта как об атомарной операции.

VD>>Теперь, что касается статических методов и свободных фенкций. Формально вдотнете нет свободных функций. И вообще — это терминология C++. Однако можно просто считатические методы и свободные функции синонимами так как если абстрагироваться от деталей, классы для статических методов скорее служат для целей выделения пространств имен/модулей. Так что по фигу как их называть.


М>"Не плоди сущности без необходимости".


Тфу, ты. Как будто в богадельню попал.
Отче, какие сущности? Есть платформа, есть используемая ею терминология.
Хочешь понимать о чем говорят и чтобы тебя понимали — изучи эту терминологию и придерживайся ее.

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


Так С++ с его RTTI идет лесом на этом форуме. Ты пришел в другую компанию. Будь добр принять ее правила и традиции.

Нет в дотнете свободных функций. Тот же C++/CLI эмулирует их создавая невидимые классы и объявляя в них статические методы. RTTI в дотнете тоже нет. Вместо него System.Reflection который позволяет получать информацию о любом типа до которого только можно дотянуться.

VD>>Просто, какое-то "Горе от ума".


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


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

Извини если покажусь надменным, но позволю дать тебе один совет. "Козьма Прутков" говорил — "Специалист подобен флюсу: полнота его односторонняя". Вот ты похоже специалист в С++. Но других вещей в жизни не видел и пытаешься судить о вещах с колокольни С++. Точнее на уровне бито/байто дробления. Меж тем есть множество других весьма увлекательных миров. Есть ФП в котором функция является объектом в большей степени нежели объектом является экземпляр класса в С++. Есть дотнет в котором есть рефлексия по сравнению с которой RTTI кажется недоразумением. Так вот нельзя все мерить одной линейкой С++ (или чего-бы то ни было). Надо изучить и понять концепции этих разных миров, изучить их терминологию, и тогда можно будет судить об "высокоинтеллектуальных" беседах более осмысленно. А так. Влез. Брякнул что-то и пошел дальше в полной уверенности что вокруг стадо баранов не понимающих как устроен мир.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[28]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 13:06
Оценка: :)
Здравствуйте, nikov, Вы писали:

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


VD>>Так что если это и баг, то в другом месте.

VD>>К рассматриваемому вопросу вывода типов конструкторов это отношения не имеет.

N>Тем не менее это показывает, что в компиляторе C# предпочитают выделять ресурсы на то, чтобы поддерживать уровень багов на низком уровне, чем на добавление множества новых фич.


Как-то им это не очень хорошо удается. Мне кажется с командой из 7 и более человек работающих полный рабочий день можно было бы и по лучше.

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

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


А я не говорю про гораздо больше. Я говорю о совсем одной и не очень уж и навороченной. Я конечно мог бы порассуждать на тему того, что при наличии готового алгоритма отдающегося под лицензией BSD ребятам из МС могли бы тупо содрать его и довести до ума. Но я понимаю, что это сверхзадача. Я говорю о совсем простом. О том, что фактически уже сделано. Остается сделать еще один шаг и применить имеющийся функционал не только к статическим методам, но и к конструкторам.

N>(разумеется, ценой уменьшения качества, стабильности и скорости компиляции).


Ты меня прости, но качество C# имеет так себе. Компилятор у него уже давно стал write-only.
Дайте мне пятую часть тех средств, что вкладывается в C# я тебе гарантирую, что стабильность, качество и скорость этого "экспериментального" языка будут как минимум не хуже чем у "промышленного".

Да и фич в немерле не сильно то больше. Просто его в отличии от C# серьезно проектировали с нуля как целостный язык, а не создали как язык у других но с событиями и свойствами, а потом начали прикручивать фичи.

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


Я тоже так раньше думал. Теперь почти уже уверен в том, что этого никогда не будет. Ну, или будет после моего ухода на пенсию. Так что я все больше и больше укрепляюсь в мысли, что проще довести до ума немерле.

Думаю, что за время пока в шарп будут добавлять полноценный вывод типов, я успею сделать n2 который будет сразу проектироваться не как студенческая работа, а как промышленное решение и которому с точки зрения расширяемости будут завидовать Nemerle, Lisp и Perl 6.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[29]: C# 4.0 Type Inference
От: nikov США http://www.linkedin.com/in/nikov
Дата: 11.09.09 13:30
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Дайте мне пятую часть тех средств, что вкладывается в C# я тебе гарантирую, что стабильность, качество и скорость этого "экспериментального" языка будут как минимум не хуже чем у "промышленного".


VD>Думаю, что за время пока в шарп будут добавлять полноценный вывод типов, я успею сделать n2 который будет сразу проектироваться не как студенческая работа, а как промышленное решение и которому с точки зрения расширяемости будут завидовать Nemerle, Lisp и Perl 6.


Ну так выложи на сайт Roadmap, повесь кнопочку Donate, и глядишь — потекут деньги от благодарных пользователей.
Re[30]: C# 4.0 Type Inference
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 13:53
Оценка:
Здравствуйте, nikov, Вы писали:

N>Ну так выложи на сайт Roadmap,


Это надо, конечно, сделать

N>повесь кнопочку Donate, и глядишь — потекут деньги от благодарных пользователей.


Мечтать не вредно .

На Donate не могут жить даже популярные проекты. А уж мы и подавно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[27]: AdvancedHints Beta
От: Мизантроп  
Дата: 11.09.09 14:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ты предлагал не рассматривать его как ординарную функцию. А как раз это решает тучу проблем.


Я не знаю, как Вы это поняли, но я как раз предлягал рассматривать конструктор вообще не как конструктор, а как инициализатор. И тогда для вызова конструктора, существующего для любого типа в единственном числе, будет достаточно иметь ссылку на метакласс. На типизированную переменную "type". И именно с точки зрения языка, абстрагируясь от реализации. И никаких проблем с неодназначностью, и никаких проблем с выводом типов, ибо с этим вполне справятся уже существующий механизм. И с обратной совместимостью тоже никаких проблем.

VD>Э... Однобокий у тебя взгляд какой-то. Просто таки просвечивает С++.

VD>Какой RTTI? (кстати в дотнете это называется рефлексия)
VD>Зачем оно тут?
VD>Мы ведь о языках говорим, а не о их рантаймах.

RTTI — это RunTime Type Information, если что. Оно не может называться рефлексией, даже в NET, просто потому, что оно — информация, данные, обобщённый термин. А рефлексия — механизм работы с этой самой информацией. Это к вопросу о терминологии.

VD>Нам нужно удобно и просто работать с конструкторами. Конечно на конструктор можно смотреть как угодно. Можно думать о нем как об инмперативной конструкции меняющей биты у объекта. Еще можно вести речь о каких то там операторах new которые выделяют память и вызвают этот императивный метод. Конечно можно! Но нужно ли?

VD>У нас есть задача — создать объект имея некоторую входную информацию. Функция справится с этой задачей на ура. При этом мы можем мыслить о создании объекта как об атомарной операции.

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

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


Не стоит извиняться, я не ребёнок, чтобы обижаться, а совет, как минимум, всегда стоит выслушать. Но Ваша манера общения мне, откровенно говоря, неприятна, а потому позвольте из этой ветки всё-же откланяться.
"Нормальные герои всегда идут в обход!"
Re[28]: AdvancedHints Beta
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.09.09 15:05
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Зачем обязательно приплетать функции к объектам там, где вполне безболезненно можно остаться в рамках объектного подхода? Вы хотите иметь возможность передавать конструктор в функцию, а я считаю это не нужным, а нужно дать полноценный метакласс, возможность объявлять переменную — ссылку на метакласс, использовать эту переменную в вызове New, и тогда эту самую переменную можно будет передавать параметром в любую функцию, какую Вам захочется. Ну вот такое вот моё личное скромное мнение.


Ну, что же. Каждый волен иметь свое мнение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[25]: AdvancedHints Beta
От: vdimas Россия  
Дата: 11.09.09 20:09
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Паттерн "Фабричный метод" пользуется таким представлением дляя инкапсуляции логики создания объекта.

VD>Так почему же нельзя рассматривать и обычные конструктораы подобным образом?

Из-за особенностей CLR, наверно.

VD>Что же это дает?

VD>...

Да понятно все и взято из практики языков с алгебраическими типами, где селектор типа используется как имя функции-конструктора типа. Здесь тоже нечто вроде подобного сугубо синтаксического выверта. Вместо всего этого потока слов можно было согласиться, что да, используется не непосредственно конструктор из CLR, а некая оберточная ф-ия, делающая new с этим конструктором.

---------
А вообще, жестокая завязка системы типов CLR сугубо на объектную модель, это такой мега-сакс, что портит массу остальных достоинств платформы. От того и возникают подобные перетирания мелочей. 1-в-1 копировать Яву вовсе не стоило.
Re[29]: C# 4.0 Type Inference
От: IT Россия linq2db.com
Дата: 11.09.09 20:30
Оценка: +2 :)))
Здравствуйте, VladD2, Вы писали:

VD>Думаю, что за время пока в шарп будут добавлять полноценный вывод типов, я успею сделать n2 который будет сразу проектироваться не как студенческая работа, а как промышленное решение и которому с точки зрения расширяемости будут завидовать Nemerle, Lisp и Perl 6.


Да подожди ты, блин. Дай линк дописать, потом мы их всех порвём
Если нам не помогут, то мы тоже никого не пощадим.
Re[28]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.09.09 06:52
Оценка: +1
Здравствуйте, Мизантроп, Вы писали:

М>Я не знаю, как Вы это поняли, но я как раз предлягал рассматривать конструктор вообще не как конструктор, а как инициализатор. И тогда для вызова конструктора, существующего для любого типа в единственном числе, будет достаточно иметь ссылку на метакласс. На типизированную переменную "type". И именно с точки зрения языка, абстрагируясь от реализации. И никаких проблем с неодназначностью, и никаких проблем с выводом типов, ибо с этим вполне справятся уже существующий механизм. И с обратной совместимостью тоже никаких проблем.

Это всё как раз понятно. Но с точки зрения потребителя получается некоторая несимметрия. "Пользовательская" функция static Foo NewFoo(int arg) будет работать как функция, а "инициализатор", который имеет точно такую же семантику, будет работать через какой-то там "метакласс".
Влад предлагает отвлечься от излишних подробностей и рассматривать конструкторы как частный случай порождающей функции.

М>Зачем обязательно приплетать функции к объектам там, где вполне безболезненно можно остаться в рамках объектного подхода? Вы хотите иметь возможность передавать конструктор в функцию, а я считаю это не нужным, а нужно дать полноценный метакласс, возможность объявлять переменную — ссылку на метакласс, использовать эту переменную в вызове New, и тогда эту самую переменную можно будет передавать параметром в любую функцию, какую Вам захочется. Ну вот такое вот моё личное скромное мнение.

Тогда в эту "любую" функцию нельзя будет передать альтернативную порождающую функцию (которая, к примеру, возвращает закешированный экземпляр вместо нового).
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[29]: AdvancedHints Beta
От: Мизантроп  
Дата: 14.09.09 07:36
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Мизантроп, Вы писали:


М>>Я не знаю, как Вы это поняли, но я как раз предлягал рассматривать конструктор вообще не как конструктор, а как инициализатор. И тогда для вызова конструктора, существующего для любого типа в единственном числе, будет достаточно иметь ссылку на метакласс. На типизированную переменную "type". И именно с точки зрения языка, абстрагируясь от реализации. И никаких проблем с неодназначностью, и никаких проблем с выводом типов, ибо с этим вполне справятся уже существующий механизм. И с обратной совместимостью тоже никаких проблем.

S>Это всё как раз понятно. Но с точки зрения потребителя получается некоторая несимметрия. "Пользовательская" функция static Foo NewFoo(int arg) будет работать как функция, а "инициализатор", который имеет точно такую же семантику, будет работать через какой-то там "метакласс".
S>Влад предлагает отвлечься от излишних подробностей и рассматривать конструкторы как частный случай порождающей функции.

Семантику как раз менять не надо. Инициализатор сейчас имеет семантику конструктора, пусть так и остаётся, только добавить возможность объявлять его виртуальным. То есть нечто вроде такого:
class Foo
{
    virual Foo(){}
}
class Bar: Foo
{
    override Bar(): Base(){}
}
metaclass FooClass: Foo;
FooClass fc = Foo;
Foo Instance = new fc(); // создали экзэмпляр Foo
fc = Bar;
Instance = new fc(); // создали экзэмпляр Bar


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

S>Тогда в эту "любую" функцию нельзя будет передать альтернативную порождающую функцию (которая, к примеру, возвращает закешированный экземпляр вместо нового).


Почему? Что мешает передать вышеуказанную fc в какую угодно функцию, либо сохранить в любом поле? Дело в том, что при передаче в функцию конструктора всё равно придётся скрыто передавать в неё и информацию о типе, иначе в функции просто невозможно будет сконструировать объект. Для его конструирования просто необходимо иметь информацию о размере объекта, чтобы выделить под него память, и реальный тип объекта, чтобы сохранить в нём ссылку на его метаинформацию. То есть по любому потребуется тот-же самый метакласс, иначе никак. Так зачем нужна лишняя сущность — конструктор — которая к тому-же ограничивает возможности?
"Нормальные герои всегда идут в обход!"
Re[30]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.09.09 08:35
Оценка:
Здравствуйте, Мизантроп, Вы писали:
М>При таком вызове и у компилятора, и у рантайма будет абсолютно вся необходимая информация для создания объекта. Единственное, что этому мешает — идеалогия. Ну как же, как конструктор может быть виртуальным? Но дело-то в том, что этот самый конструктор нигде и никогда таковым не был, а следовательно и препятствие надуманное.
Вся эта идеология уже была в полный рост освоена автором шарпа в его предыдущем языке.

S>>Тогда в эту "любую" функцию нельзя будет передать альтернативную порождающую функцию (которая, к примеру, возвращает закешированный экземпляр вместо нового).


М>Почему? Что мешает передать вышеуказанную fc в какую угодно функцию, либо сохранить в любом поле?

ОМГ. Показываю, в чём особенность:
public void Consumer(FooFactory f)
{
  var foo = f();
}

Мы хотим уметь передавать консумеру
а) ссылку на "конструктор" Foo
б) ссылку на произвольную функцию, возвращающую Foo.
Чем ты заменишь "вышеуказанную fc" для случая альтернативной порождающей функции, которая, к примеру, возвращает закешированный экземпляр вместо нового?
Если мы считаем конструктор обычным статиком, то тип FooFactory — это всего лишь синоним для Function<Foo>.


М> Дело в том, что при передаче в функцию конструктора всё равно придётся скрыто передавать в неё и информацию о типе, иначе в функции просто невозможно будет сконструировать объект. Для его конструирования просто необходимо иметь информацию о размере объекта, чтобы выделить под него память, и реальный тип объекта, чтобы сохранить в нём ссылку на его метаинформацию.

Ты лезешь в дебри. Всё это прячется внутрь замыкания.

М>То есть по любому потребуется тот-же самый метакласс, иначе никак. Так зачем нужна лишняя сущность — конструктор — которая к тому-же ограничивает возможности?

Хм. С точки зрения ФП, как раз "метакласс" является лишней сущностью, которая стоит совершенно обособленно от всех остальных "плоских функций".
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[30]: AdvancedHints Beta
От: Ziaw Россия  
Дата: 14.09.09 08:41
Оценка:
Здравствуйте, Мизантроп, Вы писали:

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


Это уже сейчас есть, рефлекшн называется. Метакласс это тип.

S>>Тогда в эту "любую" функцию нельзя будет передать альтернативную порождающую функцию (которая, к примеру, возвращает закешированный экземпляр вместо нового).


М>Почему? Что мешает передать вышеуказанную fc в какую угодно функцию, либо сохранить в любом поле? Дело в том, что при передаче в функцию конструктора всё равно придётся скрыто передавать в неё и информацию о типе, иначе в функции просто невозможно будет сконструировать объект. Для его конструирования просто необходимо иметь информацию о размере объекта, чтобы выделить под него память, и реальный тип объекта, чтобы сохранить в нём ссылку на его метаинформацию. То есть по любому потребуется тот-же самый метакласс, иначе никак. Так зачем нужна лишняя сущность — конструктор — которая к тому-же ограничивает возможности?


А вот если бы это была функция (нет ничего, что мешает ей стать таковой), то ей можно было бы манипулировать как функцией. Метакласс же сам по себе ничего не может, для него требуется инфраструктура.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[31]: AdvancedHints Beta
От: Мизантроп  
Дата: 14.09.09 09:53
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вся эта идеология уже была в полный рост освоена автором шарпа в его предыдущем языке.


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

S>>>Тогда в эту "любую" функцию нельзя будет передать альтернативную порождающую функцию (которая, к примеру, возвращает закешированный экземпляр вместо нового).


М>>Почему? Что мешает передать вышеуказанную fc в какую угодно функцию, либо сохранить в любом поле?

S>ОМГ. Показываю, в чём особенность:
S>
S>public void Consumer(FooFactory f)
S>{
S>  var foo = f();
S>}
S>

S>Мы хотим уметь передавать консумеру
S>а) ссылку на "конструктор" Foo
S>б) ссылку на произвольную функцию, возвращающую Foo.
S>Чем ты заменишь "вышеуказанную fc" для случая альтернативной порождающей функции, которая, к примеру, возвращает закешированный экземпляр вместо нового?
S>Если мы считаем конструктор обычным статиком, то тип FooFactory — это всего лишь синоним для Function<Foo>.

А зачем его чем-то заменять? Вы написали метод Consumer, принимающий параметром фабричную функцию, ну так и передавайте ему фабричную функцию, либо создающую новый экзэмпляр, либо берущий его из кэша. В чём проблема? Нет, ну я похоже действительно что-то не понимаю, но в чём будет выигрыш, ради которого есть смысл смешивать здесь объектный и функциональный подход?

М>> Дело в том, что при передаче в функцию конструктора всё равно придётся скрыто передавать в неё и информацию о типе, иначе в функции просто невозможно будет сконструировать объект. Для его конструирования просто необходимо иметь информацию о размере объекта, чтобы выделить под него память, и реальный тип объекта, чтобы сохранить в нём ссылку на его метаинформацию.

S>Ты лезешь в дебри. Всё это прячется внутрь замыкания.

Ну прячется, и что с того? Почти везде что-нибудь где-нибудь да прячется. Сохраняя метакласс с пятью конструкторами, мы можем далее вызывать по мере надобности любой из них. А сохранив делегат с конструктором, мы оказываемся жёстко привязаны к этому конструктору, и придётся хранить пять делегатов. Просто мне непонятно это стремление засунуть функциональщину куда надо и не надо. Функциональный подход, без сомнения, имеет свои сильные стороны, но господа, надо-же и меру знать

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

М>>То есть по любому потребуется тот-же самый метакласс, иначе никак. Так зачем нужна лишняя сущность — конструктор — которая к тому-же ограничивает возможности?

S>Хм. С точки зрения ФП, как раз "метакласс" является лишней сущностью, которая стоит совершенно обособленно от всех остальных "плоских функций".

А объект, о чьём конструировании мы ведём речь, есть порождение объектного подхода, а не функционального.Для него "чужеродна" как раз функциональщина, и применять её стоит там, где от этого будет действительно реальный выиграш, не достижимый в рамках объектного подхода.
"Нормальные герои всегда идут в обход!"
Re[31]: AdvancedHints Beta
От: Мизантроп  
Дата: 14.09.09 10:03
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Это уже сейчас есть, рефлекшн называется. Метакласс это тип.


Да, есть, но скорость работы ужасающа. А кроме того, не позволяет типизировать эту самую type. Впрочем, может быть я просто что-то неправильно делал? Может Вы продемонстрируете праваильный подход?

S>>>Тогда в эту "любую" функцию нельзя будет передать альтернативную порождающую функцию (которая, к примеру, возвращает закешированный экземпляр вместо нового).


Z>А вот если бы это была функция (нет ничего, что мешает ей стать таковой), то ей можно было бы манипулировать как функцией. Метакласс же сам по себе ничего не может, для него требуется инфраструктура.


А функция сама собой вызывается? Для работы с ней инфраструктуру создавать не требуется?
"Нормальные герои всегда идут в обход!"
Re[32]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.09.09 10:19
Оценка:
Здравствуйте, Мизантроп, Вы писали:
М>А я и не претендую на новизну. Но мне вот как-то не удалось найти ни одного внятного или хотя-бы полувнятного обоснования, чем она плоха. Похоже, чистый маркетинг, стремление максимальной похожести на Си.
Она плоха тем, что не нужна. Ничего фундаментально нового в язык она не привносит. Никакой "максимальной похожести на Си" в дотнете нету. И минимальной, кстати, тоже.

М>А зачем его чем-то заменять? Вы написали метод Consumer, принимающий параметром фабричную функцию, ну так и передавайте ему фабричную функцию, либо создающую новый экзэмпляр, либо берущий его из кэша. В чём проблема?

Ну вот и нет никакой проблемы. Буду передавать фабричную функцию. Где здесь место "метаклассу"? Зачем он нужен?
М>Нет, ну я похоже действительно что-то не понимаю, но в чём будет выигрыш, ради которого есть смысл смешивать здесь объектный и функциональный подход?
Как в чём? В универсальности подхода. Ты предлагаешь принимать в Consumer некий метакласс. Это, фактически, гвоздями прибивает единственную доступную реализацию. Для чего? Какой от этого бенефит? Фабричная функция, с учётом ковариантности делегатов, прекрасно покрывает сценарий "давайте передадим вместо конструктора Foo конструктор Bar: Foo.

М>Ну прячется, и что с того? Почти везде что-нибудь где-нибудь да прячется. Сохраняя метакласс с пятью конструкторами, мы можем далее вызывать по мере надобности любой из них.

А можно в студию пример сценария, где вот это вот будет хоть как-то полезно?
М> А сохранив делегат с конструктором, мы оказываемся жёстко привязаны к этому конструктору, и придётся хранить пять делегатов.
Прекрасно. Если потребителю нужно именно пять способов конструирования (что маловероятно, хотя я, в принципе, могу себе придумать экзотическое применение этой технике), то мы получаем классическое место для применения интерфейса. Т.е. у нас будет
IFooFactory
{
  Foo NewFoo(); // default constructor
  Foo NewFoo(SerializationInfo info, StreamingContext context); // serialization constructore
  Foo NewFoo(int a, int b); // constructor+initializer
}

То, что вы предлагаете — это встроенная в язык реализация этого паттерна. Она слишком редко востребована, и слишком легко может быть написана вручную. Поэтому её и не стали включаить в C#.

М>Просто мне непонятно это стремление засунуть функциональщину куда надо и не надо. Функциональный подход, без сомнения, имеет свои сильные стороны, но господа, надо-же и меру знать

А мне вот непонятно стремление засунуть ООП куда надо и не надо. Там, где можно обойтись интерфейсом, а то и просто делегатом, зачем-то предлагается тяжелая артиллерия в виде классов-синглтонов.

М>А объект, о чьём конструировании мы ведём речь, есть порождение объектного подхода, а не функционального.Для него "чужеродна" как раз функциональщина, и применять её стоит там, где от этого будет действительно реальный выиграш, не достижимый в рамках объектного подхода.


Выигрыш был озвучен в самом начале этой дискуссии. Существующее неравноправие конструкторов и статик функций приводит к необходимости писать лишний код. И, в частности, не работает вывод типов генерик-аргументов. Метаклассы эту проблему никак не решат.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[33]: AdvancedHints Beta
От: Мизантроп  
Дата: 14.09.09 11:19
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Она плоха тем, что не нужна. Ничего фундаментально нового в язык она не привносит. Никакой "максимальной похожести на Си" в дотнете нету. И минимальной, кстати, тоже.


О том, что синтаксис C# максимально приближен к Си для того, чтобы облегчить переход на нег Си-программистов, я читал ещё в начале века в высказываниях представителя Microsoft. Извините, но искать ссылку не буду.

S>Как в чём? В универсальности подхода. Ты предлагаешь принимать в Consumer некий метакласс. Это, фактически, гвоздями прибивает единственную доступную реализацию. Для чего? Какой от этого бенефит? Фабричная функция, с учётом ковариантности делегатов, прекрасно покрывает сценарий "давайте передадим вместо конструктора Foo конструктор Bar: Foo.


Никакого прибивания. Если нужен фабричный метод, надо и писать фабричный метод. Почему обязательно противопоставлять? А если нужен класс, то никто не запрещает передать туда тип любого потомка. В том числе и дженерик-тип.

М>>Ну прячется, и что с того? Почти везде что-нибудь где-нибудь да прячется. Сохраняя метакласс с пятью конструкторами, мы можем далее вызывать по мере надобности любой из них.

S>А можно в студию пример сценария, где вот это вот будет хоть как-то полезно?
М>> А сохранив делегат с конструктором, мы оказываемся жёстко привязаны к этому конструктору, и придётся хранить пять делегатов.
S>Прекрасно. Если потребителю нужно именно пять способов конструирования (что маловероятно, хотя я, в принципе, могу себе придумать экзотическое применение этой технике), то мы получаем классическое место для применения интерфейса. Т.е. у нас будет
S>
S>IFooFactory
S>{
S>  Foo NewFoo(); // default constructor
S>  Foo NewFoo(SerializationInfo info, StreamingContext context); // serialization constructore
S>  Foo NewFoo(int a, int b); // constructor+initializer
S>}
S>

S>То, что вы предлагаете — это встроенная в язык реализация этого паттерна. Она слишком редко востребована, и слишком легко может быть написана вручную. Поэтому её и не стали включаить в C#.

S>А мне вот непонятно стремление засунуть ООП куда надо и не надо. Там, где можно обойтись интерфейсом, а то и просто делегатом, зачем-то предлагается тяжелая артиллерия в виде классов-синглтонов.


И класс, и делегат, и интерфейсы — всё это порождение ООП, это не альтернатива ООП, а как раз-таки его применение.

Мы начали ходить по кругу, а в Ваших высказываниях явно звучат нотки раздражения. Давайте лучше на этом завершим дискуссию, всё равно не похоже, что сможем прийти к какому-то общему знаменателю.
"Нормальные герои всегда идут в обход!"
Re[34]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.09.09 04:49
Оценка:
Здравствуйте, Мизантроп, Вы писали:
М>О том, что синтаксис C# максимально приближен к Си для того, чтобы облегчить переход на нег Си-программистов, я читал ещё в начале века в высказываниях представителя Microsoft. Извините, но искать ссылку не буду.
Ага. А еще он похож на джаву, чтобы облегчить переход джава-программистов. И на С++, в тех же целях. Ну, и, естественно, на JavaScript.

Дело в том, что это никакого отношения к вопросу не имеет. Семантика языка радикально отличается от C.

М>Никакого прибивания. Если нужен фабричный метод, надо и писать фабричный метод. Почему обязательно противопоставлять? А если нужен класс, то никто не запрещает передать туда тип любого потомка. В том числе и дженерик-тип.

По-прежнему не вижу в этих рассуждениях ответа не простой вопрос про кэширование экземпляров. Ты, случайно, не виляешь?

М>Мы начали ходить по кругу, а в Ваших высказываниях явно звучат нотки раздражения. Давайте лучше на этом завершим дискуссию, всё равно не похоже, что сможем прийти к какому-то общему знаменателю.

... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[35]: AdvancedHints Beta
От: Мизантроп  
Дата: 15.09.09 11:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

М>>Никакого прибивания. Если нужен фабричный метод, надо и писать фабричный метод. Почему обязательно противопоставлять? А если нужен класс, то никто не запрещает передать туда тип любого потомка. В том числе и дженерик-тип.

S>По-прежнему не вижу в этих рассуждениях ответа не простой вопрос про кэширование экземпляров. Ты, случайно, не виляешь?

Да нет, я просто не понимаю, что не так с кэшированием Ваш Customer ожидает фабричный делегат? Ну и на здоровье, передайте ему такой делегат, тем-же замыканием поместив в него ссылку на метакласс. И пусть этот делегат либо берёт объект из кэша, либо создаёт новый. И дженерик здесь вполне пройдет, причём для этого будет достаточно уже существующей механики. Что не так-то? Что, если будет возможность передавать конструктор, то данная ситуация будет разруливаться как-то иначе?

Сохранение такого делегата в поле? А если в поле сохранять метакласс, то чем будет хуже? Тем что придётся дополнительно писать слово из трёх букв? Зато получим доступ к метаклассу, например, к статическим членам именно этого класса. Пять конструкторов? Да их полно, объектов с множеством конструкторов. Простой пример на вскидку — создать сокетное соединение, приняв на входе либо либо имя хоста, либо IP в Int32, либо объект IPAddress. Да ещё при этом созлавать объект не того типа, который заложил разработчик фабрики, а того, который укажет пользователь этой фабрики.

Говорю-же, по кругу ходим.
"Нормальные герои всегда идут в обход!"
Re[36]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.09.09 11:59
Оценка:
Здравствуйте, Мизантроп, Вы писали:

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


М>>>Никакого прибивания. Если нужен фабричный метод, надо и писать фабричный метод. Почему обязательно противопоставлять? А если нужен класс, то никто не запрещает передать туда тип любого потомка. В том числе и дженерик-тип.

S>>По-прежнему не вижу в этих рассуждениях ответа не простой вопрос про кэширование экземпляров. Ты, случайно, не виляешь?

М>Да нет, я просто не понимаю, что не так с кэшированием Ваш Customer ожидает фабричный делегат?

Поясняю еще раз, медленно: есть два варианта.
1. Наш кастомер ожидает фабричный делегат.
В этом варианте, зачем вообще приплетать какой-то метакласс? Зачем он вам сдался? Всё прекрасно работает безо всяких типизированных метаклассов. Можно подменить как тип создаваемого объекта (с проверкой совместимости в компайл-тайме), так и алгоритм порождения.
2. Наш кастомер ожидает метакласс.
Это, в принципе, логично. Если штатный способ конструировать объекты — это метакласс, то разработчик именно метакласс и будет ожидать. Это не ему нужно уметь брать объекты из кэша; его задача — абстрагироваться от источника объектов (иначе бы он сам сделал у себя new).
В этом случае применить кэширование интегратору такого консумера уже не удастся.

М> Ну и на здоровье, передайте ему такой делегат, тем-же замыканием поместив в него ссылку на метакласс. И пусть этот делегат либо берёт объект из кэша, либо создаёт новый. И дженерик здесь вполне пройдет, причём для этого будет достаточно уже существующей механики. Что не так-то? Что, если будет возможность передавать конструктор, то данная ситуация будет разруливаться как-то иначе?

Конечно. Не будет в принципе этого выбора — что принимать. Вы вообще отдаёте себе отчёт, что ваше предложение эквивалентно заставлению разработчика любого потребителя фабрики думать — пользоваться ли "стандартным" способом, и ограничивать гибкость, или "нестандартным", и заставлять делать замыкания даже в тривиальном случае?

Зачем вы это изобретаете? Есть еще много способов усложнить язык. Давайте их все тогда обсудим.

М>Сохранение такого делегата в поле? А если в поле сохранять метакласс, то чем будет хуже?

Тем, что от метакласса нельзя отнаследоваться. Нельзя придумать "свой" метакласс для генерации IP соединений.

М> Тем что придётся дополнительно писать слово из трёх букв? Зато получим доступ к метаклассу, например, к статическим членам именно этого класса.

ОК, отлично. Добро пожаловать, статические виртуальные члены. Давненько я вас не видел. Итак, мы уже получили два механизма виртуальности — "обычный", работающий на уровне экземпляра, и "волшебный" — работающий на уровне класса. Вы же именно это подразумеваете, правильно? Чтобы можно было делать
public class Foo
{
  public static virtual int ClassId{ get {return 1;}}
}
public class Bar: Foo
{
  public static override int ClassId{ get {return 2;}}
}

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

М>Пять конструкторов? Да их полно, объектов с множеством конструкторов. Простой пример на вскидку — создать сокетное соединение, приняв на входе либо либо имя хоста, либо IP в Int32, либо объект IPAddress. Да ещё при этом созлавать объект не того типа, который заложил разработчик фабрики, а того, который укажет пользователь этой фабрики.

Да ну. Никому это не нужно. У нас что, какое-то богатое дерево наследников у сокета? Какую именно задачу будет решать метакласс сокета в таком приложении?

М>Говорю-же, по кругу ходим.

Это вы зачем-то упорно ходите по кругу. Поймите, я все эти идеи про метаклассы передумал больше пяти лет назад, когда еще вовсю писал на дельфи. Сначала казалось странным, что такая удобная штука отсутствует. А потом оказалось, что она, в общем-то, без нужды.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[37]: AdvancedHints Beta
От: Мизантроп  
Дата: 15.09.09 14:21
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Да ну. Никому это не нужно. У нас что, какое-то богатое дерево наследников у сокета? Какую именно задачу будет решать метакласс сокета в таком приложении?


Метакласс сокета — никакую. Но он может быть частью объекта, представляющего соединения. И вот этот объект может обладать тем функционалом, каким его наполнит пользователь фабрики. То есть роль фабрики может выполнять некий менеджер, обеспечивающий функционирование транспортного уровня, оптимизируя доступ к ресурссам всех объектов-соединений.. А прикладной уровень определяет пользователь менеджера, путём написания потомков и указания менеджеру их класса. Да-да, согласен, то-же самое можно получить и другими средствами, например определением фабричного делегата.

Ну это так, на вскидку.

То есть Вы говорите, что это никому не нужно, а кэширование объектов, надо понимать, — вещь чрезвычайно востребованная программёрской общественностью, и каждому чуть ли не ежедневно приходится это делать. Видимо, Вы обладаете результатами каких-то широких статистических исследований на этот счёт, но у меня таких результов нет, потому возражать не буду. А кстати, а зачем в NET вообще кэшировать объекты? Собственно создание объекта происходит очень быстро, замечательно быстро. А раз мы запросили новый объект, то видимо намерены его инициализировать новыми данными. Тогда что мы выигрываем от кэширования? По-моему, так можно скорее создать дополнительные трудности сборщику мусара, чем получить прирост производительности. Я тут как-то проверял — оказалось, что просто создать объект заметно быстрее, чем лезть за ним в кэш. А если в условиях многопоточности, то и намного быстрее. А чем быстрее мы его "сбросим", тем проще будет сборщику — поправьте, пожалуйста, если я не прав.

S>Сначала казалось странным, что такая удобная штука отсутствует. А потом оказалось, что она, в общем-то, без нужды.


Если коротко подвести итог, то вывод таков — метакласс не нужен потому, что он не даст ничего такого, чего нельзя было-бы получить иными средствами. Я правильно понял?
"Нормальные герои всегда идут в обход!"
Re[38]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.09 02:15
Оценка: +1
Здравствуйте, Мизантроп, Вы писали:


М>Метакласс сокета — никакую. Но он может быть частью объекта, представляющего соединения. И вот этот объект может обладать тем функционалом, каким его наполнит пользователь фабрики. То есть роль фабрики может выполнять некий менеджер, обеспечивающий функционирование транспортного уровня, оптимизируя доступ к ресурссам всех объектов-соединений.. А прикладной уровень определяет пользователь менеджера, путём написания потомков и указания менеджеру их класса. Да-да, согласен, то-же самое можно получить и другими средствами, например определением фабричного делегата.

Конечно. Я не вижу места построению целого отдельного класса там, где можно обойтись
а) делегатом на существующий метод — 0 строк
б) замыканием типа (address) => new Socket(address); — 1 строка
в) замыканием более сложной природы — 3 строки.
Это так, навскидку. А вы еще и предлагаете помимо метакласса нарулить какой-то отдельный класс-менеджер. Вам что, ресурсы некуда деть?

М>То есть Вы говорите, что это никому не нужно, а кэширование объектов, надо понимать, — вещь чрезвычайно востребованная программёрской общественностью, и каждому чуть ли не ежедневно приходится это делать. Видимо, Вы обладаете результатами каких-то широких статистических исследований на этот счёт, но у меня таких результов нет, потому возражать не буду. А кстати, а зачем в NET вообще кэшировать объекты? Собственно создание объекта происходит очень быстро, замечательно быстро. А раз мы запросили новый объект, то видимо намерены его инициализировать новыми данными. Тогда что мы выигрываем от кэширования?

М>По-моему, так можно скорее создать дополнительные трудности сборщику мусара, чем получить прирост производительности.
М>Я тут как-то проверял — оказалось, что просто создать объект заметно быстрее, чем лезть за ним в кэш. А если в условиях многопоточности, то и намного быстрее. А чем быстрее мы его "сбросим", тем проще будет сборщику — поправьте, пожалуйста, если я не прав.
1. Создание объекта может быть дешёвым, а инициализация — дорогой. Если я делаю объект "число фибоначчи", которое конструируется по его номеру, то мне очень выгодно возвращать готовое число в случае его наличия.
2. Добро пожаловать в мир Resource Pools. Подключения к базе данных, потоки, и прочие системные объекты, весьма дороги в создании с нуля. Их кэширование — крайне выгодно.
3. Дело даже не в этом. Кэширование — только один из примеров, когда стратегия порождения объекта может отличаться от вызова конструктора. Вы предлагаете встроить в язык ровно один способ подмены конструирования объекта. Ваша фабрика, реализованная метаклассом, будет уметь только подменять new Base(int a) на new Derived(int a).
Это слишком узкое решение. Выигрыш от него крайне мал, а затраты — велики.
Фабрика, реализованная делегатом, будет уметь не только то, что ваша, а еще и бесчисленное множество других трюков. При этом стоить она будет гораздо меньше.

М>Если коротко подвести итог, то вывод таков — метакласс не нужен потому, что он не даст ничего такого, чего нельзя было-бы получить иными средствами. Я правильно понял?

Примерно так. Вы приводите примеры сценариев, где использование метакласса менее удобно, чем любая альтернатива.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[39]: AdvancedHints Beta
От: Мизантроп  
Дата: 16.09.09 10:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Примерно так. Вы приводите примеры сценариев, где использование метакласса менее удобно, чем любая альтернатива.


Ну я так и понял — чисто субъективная причина. Но говоря подобнык вещи, не помешает уточнять: "мне менее удобно". Не стоит расписываться сразу за всё человечество, право, не стоит. Меня Вы не убедили. Впрочем, очень даже вероятно, что причиной тому — отсутствие у меня опыта в NET. Поживём — увидим.
"Нормальные герои всегда идут в обход!"
Re[40]: AdvancedHints Beta
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.09 10:56
Оценка: +1
Здравствуйте, Мизантроп, Вы писали:
М>Ну я так и понял — чисто субъективная причина.
Нет. Когда мы говорим об удобстве разработки есть ровно одна объективная метрика: количество строк кода, которые нужно написать.
Поэтому любой подход, построенный на том, что "а вот тут мы порождаем простенький класс с тремя полями" сразу пролетает по сравнению "а вот тут мы просто присваиваем свойству делегат".
Любой подход, который требует "а вот тут нам надо заранее решить, будет ли у потомков возможность хоть что-то изменить", тоже сразу пролетает — потому что замена недофабрики-метакласса на настоящую фабрику требует переделки потребителя фабрики. Опять увеличивая количество строк кода.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[38]: AdvancedHints Beta
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.09 14:00
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Если коротко подвести итог, то вывод таков — метакласс не нужен потому, что он не даст ничего такого, чего нельзя было-бы получить иными средствами. Я правильно понял?


... иными, более простыми методами.
Не ты ли говорил о том, что не надо создавать сущностей без необходимости? Так кто же из нас предлагает идти против "бритвы Оками"?

Давай еще раз. Трактовка конструкторов как статических методов порождающих объекты дает:
1. Возможность прозрачного вывода типов для конструкторов в C# и VB.
2. Возможность применять к конструкторам те же правила, что и к обычным функциям. Это в свою очередь позволяет упростить описание языка (т.е. сам язык) и упростить компилятор. Это, так же, позволяет легко передавать конструкторы куда нам нужно и хранить их где нам нужно.

Ты же предлагаешь, грубо говоря, воплотить в языке паттерн "Фабрика классов". Которые конечно тоже лучше чем ничего, но тем не менее сложнее и не дает нам преимуществ описанных в пункте 1.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.