Объясните отличия между нижеприведенными вариантами объявления функции.
Насколько я понимаю:
В 1 можно использовать название блока в функции, хотя насколько оно здесь нужно не известно.
2 и 3 равнозначны.
В 4 нельзя использовать аргумент более одного раза.
using System.Console;
def n(f) { WriteLine(f(1, 2)); }
// 1.
n(b : {def f(x, y) { x + y }; f });
// 2.
n(fun(x, y) { x + y });
// 3.
n((x, y) => { x + y });
// 4.
n(_ + _);
P.S.
В приведенном примере сгенерированно 4 (!) класса, вместо одного
30.01.07 18:07: Перенесено модератором из 'Декларативное программирование' — IT
Здравствуйте, _nn_, Вы писали:
__>Объясните отличия между нижеприведенными вариантами объявления функции.
А что ты не понимаешь?
__>Насколько я понимаю: __>В 1 можно использовать название блока в функции, хотя насколько оно здесь нужно не известно.
Дык здесь и блок в общем-то не нужен. Это:
__>def n(f) { WriteLine(f(1, 2)); }
аналогично этому:
n({def f(x, y) { x + y }; f });
Это:
__>// 2.
__>n(fun(x, y) { x + y });
Это классическая лямбда существавала с самого зарождения языка.
__>// 3.
__>n((x, y) => { x + y });
Это применение макроса позволяющего использовать облегченный синтаксис для лямбд. Этот синтаксис более краток, но и несколько более ограничен. В общем-то, он взять из еще не вышедшего C# 3.0.
__>// 4.
__>n(_ + _);
Это частичное применение оператора (частный случай частичного применения функции. Строго говоря к лямбдам отношения не имеет. Потому о "параметрах" говоить здесь не корректно. Суть частичного применения задание значений нуля или более параметров так чтобы в итоге получить функцию. Если параметр задан с помощью "_", то он считается не заданым и соотвествует соотвесвующему параметру исходной функции.
В твоем случае ты оставил не заданными все параметры оператора "+" что привело к созданию функции аналогичной лямбде "fun(x, y) { x + y }".
__>P.S. __>В приведенном примере сгенерированно 4 (!) класса, вместо __> одного
Ну, никто не обещал супер-оптимизаций. Но по жизни ничего страшного нет. Ведь редко вслечаются столь идентичные лямбды. Да и класс в метаданных не так много отедает.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Это частичное применение оператора (частный случай частичного применения функции. Строго говоря к лямбдам отношения не имеет. Потому о "параметрах" говоить здесь не корректно. Суть частичного применения задание значений нуля или более параметров так чтобы в итоге получить функцию. Если параметр задан с помощью "_", то он считается не заданым и соотвествует соотвесвующему параметру исходной функции.
А разве частичное применение не заменяется в конечном итоге лямбдой? Что-то мне подсказывает, что _ + _ будет преобразовано именно в (x1,x2) => {x1 + x2}. Так что к лямдам имеет наипрямейшее отношение. Набросал пример, дабы проверить свои предположения, все как я и представлял:
Здравствуйте, ie, Вы писали:
ie>А разве частичное применение не заменяется в конечном итоге лямбдой?
Мало ли что чем заменяется? Вон while тоже функцией заменяется. Главное — это одтельное языковео понятие обладающее уникальными характеристиками.
ie> Что-то мне подсказывает, что _ + _ будет преобразовано именно в (x1,x2) => {x1 + x2}. Так что к лямдам имеет наипрямейшее отношение.
А именованные функции тоже? Может оператор в именованную функцию заменяется? А классы? Ведь реально лямбды тоже в классы превращаютя?
На таком уровне просто не нужно думать. Абстракции на то и абстракции чтобы не обращать внимание на не существенные детали.
Фактически частичное применение было придумано для того чтобы компенсировать невозможность применения каринга.
А так... конечно, любую операцию над фукнций можно выразить через люмбду. Но это как бы еще Черч (или как там его) описал в своих работах.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>>Это применение макроса позволяющего использовать облегченный синтаксис для лямбд. Этот синтаксис более краток, но и несколько более ограничен.
PI>а в чем ограничения?
Здравствуйте, Алексей П, Вы писали:
АП>Нельзя явно указать тип возвращаемого значения.
Это как раз фигня, так как в Немерле можно задавать тип любого выражения в любом месте.
Ограничения в том, что макросная лямбда не позволяет задавать параметры итпов и не позоволяет делать из тела функции паттерн-матчинг.
Так я могу написаль к примеру следующий код:
using System.Console;
using Nemerle.Utility;
[Record]
public class A
{
public Value : string = "default";
public override ToString() : string { Value }
}
def f = fun[T](a : T) where T: class, new() { | null => T() | _ => a };
WriteLine(f(A("test")));
WriteLine(f(null : A));
В реальной жизни подобное приходится писать крайне редко, так что на практике разницы практически нет.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Ограничения в том, что макросная лямбда не позволяет задавать параметры итпов и не позоволяет делать из тела функции паттерн-матчинг.
Да, действительно, я думал что можно... никогда не приходилось их там задавать.
Здравствуйте, Алексей П, Вы писали:
АП>Здравствуйте, PhantomIvan, Вы писали:
VD>>>
__>>>>// 3.
__>>>>n((x, y) => { x + y });
VD>>>
VD>>>Это применение макроса позволяющего использовать облегченный синтаксис для лямбд. Этот синтаксис более краток, но и несколько более ограничен.
PI>>а в чем ограничения?
АП>Нельзя явно указать тип возвращаемого значения.
Нужно добавить эту возможность в макрос и тогда разницы не будет никакой.
Почему разработчики Nemerle не добавили ?
Здравствуйте, _nn_, Вы писали:
__>Нужно добавить эту возможность в макрос и тогда разницы не будет никакой. __>Почему разработчики Nemerle не добавили ?
__>Например такой синтаксис:
__>
__>n((x, y) : int => { x + y });
__>
Не пойдёт. Потому что если вводить возможность указания всех типов, то бесскобочная форма станет неопределенной. Что например значит это:
$name : $type => $code
? Тип указан для параметра или для результата?
Да и не нужно это всё, так как есть длинная лямбда.
Здравствуйте, _nn_, Вы писали:
__>Нужно добавить эту возможность в макрос и тогда разницы не будет никакой. __>Почему разработчики Nemerle не добавили ?
Потому что на фиг не надо (это даже не вдаваясь в то есть ли какие-то проблемы или нет).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, PhantomIvan, Вы писали:
VD>>Ограничения в том, что макросная лямбда не позволяет задавать параметры итпов и не позоволяет делать из тела функции паттерн-матчинг.
PI>сокращенный синтаксис для паттерн матчинга работает, я проверил PI>(в c#3-подобной лямбде)
Речь о короткой лямбде, args => body. Там не работает.
VD>>>Ограничения в том, что макросная лямбда не позволяет задавать параметры итпов и не позоволяет делать из тела функции паттерн-матчинг.
PI>>сокращенный синтаксис для паттерн матчинга работает, я проверил PI>>(в c#3-подобной лямбде)
АП>Речь о короткой лямбде, args => body. Там не работает.
Здравствуйте, PhantomIvan, Вы писали:
PI>>>сокращенный синтаксис для паттерн матчинга работает, я проверил PI>>>(в c#3-подобной лямбде)
АП>>Речь о короткой лямбде, args => body. Там не работает.
PI>да, я о ней и говорил:
Проверил, действительно работает... неделю назад не было, тоже проверял!
PI>>>>сокращенный синтаксис для паттерн матчинга работает, я проверил PI>>>>(в c#3-подобной лямбде)
АП>>>Речь о короткой лямбде, args => body. Там не работает.
PI>>да, я о ней и говорил:
АП>Проверил, действительно работает... неделю назад не было, тоже проверял!
АП>>Нельзя явно указать тип возвращаемого значения.
VD>Это как раз фигня, так как в Немерле можно задавать тип любого выражения в любом месте.
VD>Ограничения в том, что макросная лямбда не позволяет задавать параметры итпов и не позоволяет делать из тела функции паттерн-матчинг.
VD>Так я могу написаль к примеру следующий код: VD>
VD>def f = fun[T](a : T) where T: class, new() { | null => T() | _ => a };
VD>
VD>В реальной жизни подобное приходится писать крайне редко, так что на практике разницы практически нет.
где я задаю тип параметра явно, работает
может быть в более сложных случаях, включающих несколько параметров, ограничения параметров, не работает — не знаю, не проверял пока