ФПвC#3

Персональный блог одноименного форумчанина. Человека и парохода, не побоюсь этого сравнения :)

Модератор: tyomitch

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

ФПвC#3

Сообщение tyomitch » 25.06.2006 (Вс) 20:03

(Для дополнительной интриги, пробелы в заголовке пропущены. Вроде бы, его читабельность от этого не страдает.)

* Как я уже отмечал раньше, понятие "функция" по-разному трактуется в ФП и в традиционном процедурном программировании.

В Си и подобных ему языках функция -- это блок кода, выполнение (вызов) которого -- элементарная операция. Функция может принимать аргументы, может возвращать значение, но не обязана делать ни то, ни другое.

В ФП, как и в математике вообще, функция -- это сопоставление значению аргументов значения функции. Там функция не вызывается, а вычисляется. Если функция чистая, т.е. не имеет побочных эффектов, то компилятор может даже где-нибудь кешировать её значение. Функция, не принимающая аргументов, имеет весьма ограниченный смысл (это может быть Rnd, константа или что-нибудь в этом роде); функция, не возвращающая значения, не имеет смысла вовсе.

* В C# 3.0 будут функции обоих этих родов. Для объявления функций "в стиле ФП" добавится уйма шаблонов типа Func<...> и оператор =>, сопоставляющий функции её значение.

Эрик Липперт писал(а):Раньше [в C# 2.0], чтобы создать функцию, принимающую int и возвращающую функцию из int в int, нужно было делать что-то наподобие этого:

Код: Выделить всё
delegate int D1(int y);
delegate D1 D2(int x);
//...
D2 makeAdder = delegate(int x){
  return delegate(int y){
    return x + y;
  };
};
D1 addTen = makeAdder(10);
Console.WriteLine(addTen(20));


Теперь же [в C# 3.0] у нас в стандартной бибилиотеке будут такие объявления:

Код: Выделить всё
delegate R Func<R>();
delegate R Func<A1, R>(A1 a1);
delegate R Func<A1, A2, R>(A1 a1, A2 a2);
delegate R Func<A1, A2, A3, R>(A1 a1, A2 a2, A3 a3);
//...и т.д., для любого разумного числа аргументов


Так что можно будет использовать их совместно с лямбдами [оператором =>], чтобы сделать наш код намного проще и прозрачнее:

Код: Выделить всё
Func<int, Func<int, int>> makeAdder = x=>(y=>x+y); //скобки необязательны
Func<int, int> addTen = makeAdder(10);
Console.WriteLine(addTen(20));


Интересно, что не любой делегат, который можно было объявить со старым синтаксисом, можно будет объявить при помощи этих шаблонов. Очевидные примеры -- делегаты, возвращающие void, или имеющие параметры с модификаторами out или ref.


* Далее он отмечает, что новым способом нельзя объявить рекурсивные делегаты, в том числе самый функциональный из всех возможных делегатов -- функцию, принимающую аргументом функцию и возвращающую функцию, где каждая из этих функций сама принимает аргументом функцию и возвращает функцию:
Код: Выделить всё
delegate D D(D d);

Такая функция называется комбинатором и образует основу всего лямбда-исчисления, основы ФП. То, что даже с новыми функциональными возможностями в C# 3.0 для использования основы основ ФП потребуется прибегать к "функциям в стиле Си" -- по меньшей мере, забавно.
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.08.2006 (Пт) 20:20

Чен объявил неделю .net-а, и запостил серию статей об анонимных делегатах (замыканиях) в C# 2.0
http://blogs.msdn.com/oldnewthing/
Изображение


Вернуться в Tyomitch

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 15

    TopList