[C#, Этюд] Лямбды и делегаты
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.03.10 14:44
Оценка:
Обычный вопрос: скомпилируется ли программа, и если да, то что она напечатает?

using System;

class A
{
  static void Foo(string x, Action<Action> y) { Console.WriteLine(1); }
  static void Foo(object x, Func<Func<int>,int> y) { Console.WriteLine(2);}

  static void Main()
  {
    Foo(null, x => x());
    Foo(null, x => (x()));
  }
}
Re: [C#, Этюд] Лямбды и делегаты
От: Пельмешко Россия blog
Дата: 14.03.10 16:52
Оценка:
Здравствуйте, nikov, Вы писали:

N>Обычный вопрос: скомпилируется ли программа, и если да, то что она напечатает?


Скомпилируется и напечатает:
1
2


Рассмотрим второй случай:
Foo(null, x => (x()));

Отбираем applicable function members. Рассмотрим перегрузку void Foo(string x, Action<Action> y).
Существует неявное приведение null к string, но существует ли приведение лямбды x => (x()) к типу делегата Action<Action>?
Одно из правил приведений анонимных методов к типам делегатов гласит:

• If D has a void return type and the body of F is an expression, when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt §7) that would be permitted as a statement-expression (§8.6).


То есть тело (x()) должно быть валидным statement-expression, что в нашем случае не выполняется, так как (x()) является parenthesized-expression. Можно убедиться в невозможности приведения на таком примере:
Action<Action> a = x => (x());
//  ERROR CS0201: Only assignment, call, increment, decrement,
//  and new object expressions can be used as a statement.

Остаётся только вторая перегрузка. Не составляет труда убедиться, что она является applicable, так как действует правило:

6.5 Anonymous function conversions
• If D has a non-void return type and the body of F is an expression, when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt §7) that is implicitly convertible to the return type of D.



Теперь первый случай:
Foo(null, x => x());

Согласно тому же 6.5 Anonymous function conversions отберём applicable-перегрузки:


Оке, значит будем выяснять какая перегрузка лучше:

7.4.3.2 Better function member
• for each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and
• for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.


Выясняем какое приведение типов лучше: null -> object или null -> string, ну тут уж всё совсем просто:

7.4.3.4 Better conversion from type
• If an implicit conversion from T1 to T2 exists, and no implicit conversion from T2 to T1 exists, C1 is the better conversion.


Так как существует неявное приведение string -> object, то приведение null -> string будет являться better conversion, а значит в результате overload resolution будет выбрана перегрузка void Foo(string x, Action<Action> y).
Re[2]: [C#, Этюд] Лямбды и делегаты
От: Пельмешко Россия blog
Дата: 14.03.10 17:13
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Так как существует неявное приведение string -> object, то приведение null -> string будет являться better conversion, а значит в результате overload resolution будет выбрана перегрузка void Foo(string x, Action<Action> y).


Наверное ещё стоит добавить, что ни одно из приведений лямбды x => x() к типам делегатов Action<Action> и Func<Func<int>, int> не является better conversion from expression, поэтому overload resolution достаточно сравнения первых параметров перегрузок
Re: [C#, Этюд] Лямбды и делегаты
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.03.10 21:27
Оценка:
Здравствуйте, nikov, Вы писали:

N>Обычный вопрос: скомпилируется ли программа, и если да, то что она напечатает?

N>
N>using System;

N>class A
N>{
N>  static void Foo(string x, Action<Action> y) { Console.WriteLine(1); }
N>  static void Foo(object x, Func<Func<int>,int> y) { Console.WriteLine(2);}

N>  static void Main()
N>  {
N>    Foo(null, x => x());
N>    Foo(null, x => (x()));
N>  }
N>}
N>


Не скомпилируется. Скажет:
Main.n(16,3):Error: each overload has an error during call:
Main.n(16,3):Error: overload #1, "method Program.Foo(_N_wildcard_2768 : object, _N_wildcard_2769 : System.Func[System.Func[int], int]) : void" fail because:
Main.n(16,3):Error: in argument #2 (_N_wildcard_2769), needed a System.Func[System.Func[int], int], got void -> ?+ -> ?: void -> ?+ -> ? is not a subtype of System.Func[System.Func[int], int] [simple require]
Main.n(13,2):Warning: hint: overload defination
Main.n(16,3):Error: overload #2, "method Program.Foo(_N_wildcard_2766 : string, _N_wildcard_2767 : System.Action[System.Action]) : void" fail because:
Main.n(16,3):Error: in argument #2 (_N_wildcard_2767), needed a System.Action[System.Action], got void -> ?+ -> ?: void -> ?+ -> ? is not a subtype of System.Action[System.Action] [simple require]
Main.n(12,2):Warning: hint: overload defination
39.


... если компилировать сами знаете чем
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [C#, Этюд] Лямбды и делегаты
От: Пельмешко Россия blog
Дата: 16.03.10 08:01
Оценка: -1
Здравствуйте, VladD2, Вы писали:

VD>Не скомпилируется. Скажет:

Main.n(16,3):Error: each overload has an error during call:
Main.n(16,3):Error: overload #1, "method Program.Foo(_N_wildcard_2768 : object, _N_wildcard_2769 : System.Func[System.Func[int], int]) : void" fail because:
Main.n(16,3):Error: in argument #2 (_N_wildcard_2769), needed a System.Func[System.Func[int], int], got void -> ?+ -> ?: void -> ?+ -> ? is not a subtype of System.Func[System.Func[int], int] [simple require]
Main.n(13,2):Warning: hint: overload defination
Main.n(16,3):Error: overload #2, "method Program.Foo(_N_wildcard_2766 : string, _N_wildcard_2767 : System.Action[System.Action]) : void" fail because:
Main.n(16,3):Error: in argument #2 (_N_wildcard_2767), needed a System.Action[System.Action], got void -> ?+ -> ?: void -> ?+ -> ? is not a subtype of System.Action[System.Action] [simple require]
Main.n(12,2):Warning: hint: overload defination 39.


VD>... если компилировать сами знаете чем


Влад, а можете объяснить что это такое:
void -> ?+ -> ?: void -> ?+ -> ?
Это что ли user-friendly сообщение об ошибке?
Неужели нельзя взять в скобочки функциональный тип, как в F#, чтобы два упоминания типа не сливались вместе в не пойми что?

p.s. Хотел тут бету скачать, с макросами поиграть, но что-то после таких сообщений об ошибках... "?+", "?" брр
Re[3]: [C#, Этюд] Лямбды и делегаты
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.03.10 10:26
Оценка:
Здравствуйте, Пельмешко, Вы писали:
П>Main.n(16,3):Error: in argument #2 (_N_wildcard_2769), needed a System.Func[System.Func[int], int], got void -> ?+ -> ?: void -> ?+ -> ? is not a subtype of System.Func[System.Func[int], int] [simple require]

П>Влад, а можете объяснить что это такое:

П>
П>void -> ?+ -> ?: void -> ?+ -> ?
П>
Это что ли user-friendly сообщение об ошибке?


После двоеточия идет описание вложенной ошыбки приведшей к появлению основной. В данном случае это результат операции require.

П>Неужели нельзя взять в скобочки функциональный тип, как в F#, чтобы два упоминания типа не сливались вместе в не пойми что?


Согласен, что можно было бы лучше описание ошибки дать. Но это весьма старый код и на его доработку просто не хватает времени. Что до скобок, то они будут лишние. Обычно и так все ясно. В Немерле, в отличии от F# параметры всегда являются ортежем. Здесь же смущает скорее то, что после двоеточия идет еще одно сообщение которое тоже начинается с описания того же типа.

П>p.s. Хотел тут бету скачать, с макросами поиграть, но что-то после таких сообщений об ошибках... "?+", "?" брр


Ну, не качай, если тебе приятна логика по которой работает компилятор C# в этюдах Никова .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [C#, Этюд] Лямбды и делегаты
От: Воронков Василий Россия  
Дата: 16.03.10 12:37
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>p.s. Хотел тут бету скачать, с макросами поиграть, но что-то после таких сообщений об ошибках... "?+", "?" брр


Чувак, да ты становишься эстетом
Вообще же понятно, в чем проблема, она в эксепшине описана. Что, не нравится? Ты на С++ не писал?
Re[4]: [C#, Этюд] Лямбды и делегаты
От: Пельмешко Россия blog
Дата: 16.03.10 15:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Согласен, что можно было бы лучше описание ошибки дать. Но это весьма старый код и на его доработку просто не хватает времени. Что до скобок, то они будут лишние. Обычно и так все ясно. В Немерле, в отличии от F# параметры всегда являются ортежем. Здесь же смущает скорее то, что после двоеточия идет еще одно сообщение которое тоже начинается с описания того же типа.


Именно это и смутило, два типа слились в одну кашу.
Насчёт скобок — простите, не знал, что в немерле типы вообще не принято выделять из общего сообщения об ошибке:
mutable a = "abc";
a = 1;
// expected string-, got int in assigned value: the types int and string are not compatible [simple unify]


П>>p.s. Хотел тут бету скачать, с макросами поиграть, но что-то после таких сообщений об ошибках... "?+", "?" брр


VD>Ну, не качай, если тебе приятна логика по которой работает компилятор C# в этюдах Никова .


Мне не особо приятен результат (и я на самом деле предпочитаю поведение Немерле в подобных тяжёлых случаях overload resolution — бросить ambiguous), но всё же приятно, что компилятор действует по спецификации, а ещё приятно что эта спецификация существует и имеет очень достойное качество

Всё, что я хотел сказать вообще тем сообщением — только то, что мнение о языке складывается из таких вот мелочей.
Я вроде не дурак, а понять что это за void -> ?+ -> ?: void -> ?+ -> ? не сразу получилось, вот и всё!
Re[5]: [C#, Этюд] Лямбды и делегаты
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.03.10 15:48
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Мне не особо приятен результат (и я на самом деле предпочитаю поведение Немерле в подобных тяжёлых случаях overload resolution — бросить ambiguous), но всё же приятно, что компилятор действует по спецификации, а ещё приятно что эта спецификация существует и имеет очень достойное качество


Ну, так внеси свой вклад. Сделай проект лучше.

П>Всё, что я хотел сказать вообще тем сообщением — только то, что мнение о языке складывается из таких вот мелочей.

П>Я вроде не дурак, а понять что это за void -> ?+ -> ?: void -> ?+ -> ? не сразу получилось, вот и всё!

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

Согласись, это будет несколько конструктивнее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [C#, Этюд] Лямбды и делегаты
От: Пельмешко Россия blog
Дата: 16.03.10 15:50
Оценка: +1 :)
Здравствуйте, Воронков Василий, Вы писали:

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


П>>p.s. Хотел тут бету скачать, с макросами поиграть, но что-то после таких сообщений об ошибках... "?+", "?" брр


ВВ>Чувак, да ты становишься эстетом


Не помню момент когда мы с Вами стали общаться на "чувак".

ВВ>Вообще же понятно, в чем проблема, она в эксепшине описана. Что, не нравится? Ты на С++ не писал?


Ну расскажите мне про то, какой ужас производать на выхлопе С++, когда не может инстанцировать 20 раз вложенный во что-нибудь шаблон и что мне надо поклониться до земли Владу за то, что компилятор Немерле вообще ещё жив и умеет генерировать сообщения об ошибках.

Если Вы не согласны с моим сообщением, то его всегда можно минусануть, всего и делов то, "чувак".
чувак
Re[5]: [C#, Этюд] Лямбды и делегаты
От: Воронков Василий Россия  
Дата: 16.03.10 16:05
Оценка: +1
Здравствуйте, Пельмешко, Вы писали:

ВВ>>Чувак, да ты становишься эстетом

П>Не помню момент когда мы с Вами стали общаться на "чувак".

А, ну извините. Теперь буду только "Вы".

ВВ>>Вообще же понятно, в чем проблема, она в эксепшине описана. Что, не нравится? Ты на С++ не писал?

П>Ну расскажите мне про то, какой ужас производать на выхлопе С++, когда не может инстанцировать 20 раз вложенный во что-нибудь шаблон и что мне надо поклониться до земли Владу за то, что компилятор Немерле вообще ещё жив и умеет генерировать сообщения об ошибках.

Не использовать язык просто потому, что тебе не нравится как *отформатировано* сообщение об ошибке, это... Впрочем, я сегодня вежливый, на "вы", так что сам догадаешься.
Re[5]: [C#, Этюд] Лямбды и делегаты
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.03.10 16:16
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Ну расскажите мне про то, какой ужас производать на выхлопе С++, когда не может инстанцировать 20 раз вложенный во что-нибудь шаблон и что мне надо поклониться до земли Владу за то, что компилятор Немерле вообще ещё жив и умеет генерировать сообщения об ошибках.


П>Если Вы не согласны с моим сообщением, то его всегда можно минусануть, всего и делов то, "чувак".


По форме Воронков конечно не прав, но по сути — прав. Отказываться от языка потому-что где-то увидел не очень красиво оформленное сообщение об ошибке — это мягко говоря не конструктивно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [C#, Этюд] Лямбды и делегаты
От: Пельмешко Россия blog
Дата: 16.03.10 17:31
Оценка:
Здравствуйте, VladD2, Вы писали:

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


П>>Ну расскажите мне про то, какой ужас производать на выхлопе С++, когда не может инстанцировать 20 раз вложенный во что-нибудь шаблон и что мне надо поклониться до земли Владу за то, что компилятор Немерле вообще ещё жив и умеет генерировать сообщения об ошибках.


П>>Если Вы не согласны с моим сообщением, то его всегда можно минусануть, всего и делов то, "чувак".


VD>По форме Воронков конечно не прав, но по сути — прав. Отказываться от языка потому-что где-то увидел не очень красиво оформленное сообщение об ошибке — это мягко говоря не конструктивно.


Сути?! По какой сути?! Где?! Где я написал, что отказался от языка?!?

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

Ради Бога, не надо за меня домысливать от чего я отказываюсь, чёрт меня дёрнул вообще Вам ответить.
Re[7]: [C#, Этюд] Лямбды и делегаты
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.03.10 17:39
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Сути?! По какой сути?! Где?! Где я написал, что отказался от языка?!?


Это твои слова:

p.s. Хотел тут бету скачать, с макросами поиграть, но что-то после таких сообщений об ошибках... "?+", "?" брр

Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [C#, Этюд] Лямбды и делегаты
От: vdimas Россия  
Дата: 17.03.10 09:18
Оценка: +1
Здравствуйте, nikov, Вы писали:

N>Обычный вопрос: скомпилируется ли программа, и если да, то что она напечатает?


Очередной раз можно посожалеть, что молча скомпилируется...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.