Функциональное программирование для всех
От: Линкер Николай (перевод) Россия lj://_lcr_
Дата: 30.07.06 05:52
Оценка: 3220 (64) +4 -3
Статья:
Вячеслав Ахмечет. Функциональное программирование для всех
Автор(ы): Вячеслав Ахмечет
Дата: 16.09.2006
Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.


Авторы:
Линкер Николай (перевод)

Аннотация:
Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re: Функциональное программирование для всех
От: dikun Беларусь  
Дата: 16.09.06 21:39
Оценка:
> Функции обозначались греческой буквой ?

Это мой браузер (Opera 9.00 Build 8212 — Windows Server 2003) шутит или буква "лямбда" не напечатана?
Re[2]: Функциональное программирование для всех
От: StatujaLeha на правах ИМХО
Дата: 17.09.06 05:45
Оценка:
Здравствуйте, dikun, Вы писали:

>> Функции обозначались греческой буквой ?


D>Это мой браузер (Opera 9.00 Build 8212 — Windows Server 2003) шутит или буква "лямбда" не напечатана?


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

toAll: Может кто-нибудь знает, как лечиться?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Функциональное программирование для всех
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 17.09.06 06:56
Оценка:
Здравствуйте, dikun, Вы писали:

>> Функции обозначались греческой буквой ?

D>Это мой браузер (Opera 9.00 Build 8212 — Windows Server 2003) шутит или буква "лямбда" не напечатана?

частично исправлено — IE отображает лямбды правильно, а вот FireFox не хочет
... << RSDN@Home 1.2.0 alpha rev. 654>>
Re[3]: Функциональное программирование для всех
От: Centaur Россия  
Дата: 17.09.06 07:56
Оценка: +1
Здравствуйте, Odi$$ey, Вы писали:

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


>>> Функции обозначались греческой буквой ?

D>>Это мой браузер (Opera 9.00 Build 8212 — Windows Server 2003) шутит или буква "лямбда" не напечатана?

OE>частично исправлено — IE отображает лямбды правильно, а вот FireFox не хочет


Нужно заменить в исходнике все вхождения
<span style="font-family: Symbol;">l</span>

на
&lambda;

и аналогично для всех остальных букв.
Re[2]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 18.09.06 01:56
Оценка:
dikun,

>> Функции обозначались греческой буквой ?


D>Это мой браузер (Opera 9.00 Build 8212 — Windows Server 2003) шутит или буква "лямбда" не напечатана?


Нет, с браузером всё в порядке. В качестве теста см:
Греческие буквы в HTML

&amp;#955;
λ

Где-то в цепочке преобразований XML->...->HTML->View происходит лишний эскейпинг...
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: Функциональное программирование для всех
От: PVA  
Дата: 16.10.06 11:31
Оценка: :))) :))
Спасибо за статью!

Параллелизм

В условиях независимости от внешнего состояния оно может быть распараллелено и в традиционных случаях. Разве нет?

Горячая замена кода

Сериализация не поможет?

Функции высшего порядка

А с коленки реализация не подойдет?
struct op_t
{
    virtual int operator()(int a, int b) = 0;
};

struct op_add : public op_t
{
    virtual int operator()(int a, int b)
    {
        return a + b;
    }
};

void show(int a, int b, op_t & op)
{
    printf("%d\n", op(a, b));
}

int main(int argc, char* argv[])
{
    op_add add;

    show(4, 5, add);

    return 0;
}

Аналогично для приведенного обработчика может быть реализована необходимая схема. Соответсвенно, вот это

...Мы вынуждены создать два новых типа просто для поддержки различного клиентского кода!...

и сопутствующий текст выглядит странно.

Карринг

#define square(x) pow((x), 2)


Ленивые вычисления

А разве оптимизаторы нынешние не делают то же самое?

Абстрагирование от управляющих структур

Аналогично функциям высшего порядка.

Бесконечные структуры данных

Шаблоны с++ + метапрограммирование?

Продолжения

Аналогично функциям высшего порядка.

Сопоставление с образцом

Шаблоны?

Замыкания

Function makePowerFn(int power)
{
   int powerFn(int base)
   {
     return pow(base, power);
   }

   return powerFn;
}

Function square = makePowerFn(2);
square(3); // возвращает 9

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

В свете изложенных соображений, что мешает програмить на с++ в ФП?
newbie
Re[4]: Функциональное программирование для всех
От: FR  
Дата: 16.10.06 11:43
Оценка: +1 :)
Здравствуйте, PVA, Вы писали:

PVA>В свете изложенных соображений, что мешает програмить на с++ в ФП?


Ничего ни мешает, но это также удобно как ООП на ассемблере.
Re[4]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 16.10.06 13:32
Оценка: 2 (1)
PVA,

Начну с последнего вопроса, ок?

PVA>В свете изложенных соображений, что мешает програмить на с++ в ФП?

В мелких дозах ничего не мешает, в крупных — 10й закон Гринспуна. Чтобы воспользоваться преимуществами функционального программирования, вам нужно будет создать строительные блоки на C++ и работать используя только эти строительные блоки. Вместе с тем у меня возникают большие сомнения в том, что некоторые строительные блоки реализуемы эффективно и удобно или вообще реализуемы. Кроме того, такой способ приведёт к тому, что вы не сможете воспользоваться большинством оптимизаций, которые делают компиляторы функциональных языков (например, уничтожение промежуточного копирования, хвостовая рекурсия и т.п.).

PVA>

Параллелизм

PVA>В условиях независимости от внешнего состояния оно может быть распараллелено и в традиционных случаях. Разве нет?
Да, конечно. До тех пор, пока это будет описываться программистом _явно_.

PVA>

Горячая замена кода

PVA>Сериализация не поможет?
Не поможет. Возьмём пример на Яве. Пусть у нас интерфейс CSDescriptor:
public interface CSDescriptor extends Serializable {
    /**
     *  @return descriptor type
     */
    String getDescriptorType();
}

Мы берём, и рефакторим до
public interface CSDescriptor extends Serializable {
    /**
     *  @return descriptor type
     */
    String getDescriptorType(Object param);
}

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

PVA>

Функции высшего порядка

PVA>А с коленки реализация не подойдет?
PVA>
struct op_t
PVA>{
PVA>    virtual int operator()(int a, int b) = 0;
PVA>};

PVA>struct op_add : public op_t
PVA>{
PVA>    virtual int operator()(int a, int b)
PVA>    {
PVA>        return a + b;
PVA>    }
PVA>};

PVA>void show(int a, int b, op_t & op)
PVA>{
PVA>    printf("%d\n", op(a, b));
PVA>}

PVA>int main(int argc, char* argv[])
PVA>{
PVA>    op_add add;

PVA>    show(4, 5, add);

PVA>    return 0;
PVA>}

PVA>Аналогично для приведенного обработчика может быть реализована необходимая схема. Соответсвенно, вот это
PVA>

...Мы вынуждены создать два новых типа просто для поддержки различного клиентского кода!...

PVA>и сопутствующий текст выглядит странно.

Мне бы op_t принимающую любое количество параметров любого типа... Причём вместо создания экземпляра типа op_add я хочу просто писать (+).

PVA>

Карринг

PVA>
#define square(x) pow((x), 2)

... а вместо создания экземпляра типа op_add_xX(2) я хочу писать (+2) (ну или (_ + 2)), вместо создания экземпляра типа op_add_Xx(2) хочу писать (2+) (или (2 + _)), а вместо создания экземпляра op_add_XX(2,3) я хочу писать 2 + 3. Ну и конечно передать полученные функции куда нибудь в ФВП.

PVA>

Ленивые вычисления

PVA>А разве оптимизаторы нынешние не делают то же самое?
Если могут — делают, но почти всегда не могут. А не могут, потому что когда вы пишете foo(x, y), то аргументы x и y должны быть вычислены до того, как управление передастся в функцию foo.

PVA>

Абстрагирование от управляющих структур

PVA>Аналогично функциям высшего порядка.
Возможно у вас есть свежая идея. Поделитесь?

PVA>

Бесконечные структуры данных

PVA>Шаблоны с++ + метапрограммирование?
Возможно у вас есть ещё одна свежая идея. Мне будет очень интересно.

PVA>

Продолжения

PVA>Аналогично функциям высшего порядка.
Здесь если покопать, то лес настолько дремучий, что связываться с этим не захочется. Есть реализация продолжений и на Яве, и на C, и на C#. Но все они неуниверсальны и интрузивны для клиентского кода. Поизвращаться над своим кодом я и так могу, без продолжений (тем более что "продолжения" на списках сделает любой нормальный студент, не слишком сложная задача), а что делать с rt.jar?

PVA>

Сопоставление с образцом

PVA>Шаблоны?
Сопоставление с образцом уж точно не реализуемо на шаблонах. Максимум, что можно выжать, это boost::tie.

PVA>

Замыкания

PVA>
Function makePowerFn(int power)
PVA>{
PVA>   int powerFn(int base)
PVA>   {
PVA>     return pow(base, power);
PVA>   }

PVA>   return powerFn;
PVA>}

PVA>Function square = makePowerFn(2);
PVA>square(3); // возвращает 9

PVA>Не совсем понятно, каким образом происходит вызов powerFn неявно, аналогично с инкрементом.
Это псевдокод. Можно было написать ещё
Function makePowerFn(int power)
{
return new Function( int powerFn(int base) { return pow (base, power); } );
}
как вариант. Но это тоже не Ява. Идея состоит в том, чтобы вернуть функцию, причём связанную с внешним параметром.

PVA>А реализовано может быть через те же функторы.

Это вы делаете вывод исходя из ошибочного предположения, что функции высшего порядка == функторы. А на самом деле функторами можно эмулировать ФВП (так же как это делает компилятор написанный на C).

Я с удовольствием послушаю, как вы реализуете на функторах функцию iterate:
let compose f g x = f(g x) ;;
let rec iterate n f =
    if n = 0 then (function x -> x)
    else compose f (iterate (n-1) f) ;;

(* использовать можно так *)
let rec power i n =
    let i_times = ( * ) i in  (* "i_times n" равно функции "умножить на i" n раз *)
        iterate n i_times 1 ;;

power 2 8 ;; (* выдаст 256 *)

(ocaml)
Больше чем уверен, что вы вернёте разве что функтор-интерпретатор, который будет инкапсулировать АСТ.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[5]: Функциональное программирование для всех
От: Кодт Россия  
Дата: 16.10.06 15:42
Оценка: 2 (2)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

PVA>>А реализовано может быть через те же функторы.

LCR>Это вы делаете вывод исходя из ошибочного предположения, что функции высшего порядка == функторы. А на самом деле функторами можно эмулировать ФВП (так же как это делает компилятор написанный на C).

LCR>Я с удовольствием послушаю, как вы реализуете на функторах функцию iterate:

LCR>let compose f g x = f(g x) ;;
LCR>let rec iterate n f =
LCR>    if n = 0 then (function x -> x)
LCR>    else compose f (iterate (n-1) f) ;;

LCR>(* использовать можно так *)
LCR>let rec power i n =
LCR>    let i_times = ( * ) i in  (* "i_times n" равно функции "умножить на i" n раз *)
LCR>        iterate n i_times 1 ;;

LCR>power 2 8 ;; (* выдаст 256 *)

LCR>(ocaml)
LCR>Больше чем уверен, что вы вернёте разве что функтор-интерпретатор, который будет инкапсулировать АСТ.

Во-первых: а что здесь вообще можно вернуть? Какой код порождает компилятор caml?
— строит AST
— приводит к форме, свободной от переменных, т.е. к коду для комбинаторной машины — опять же, в каком базисе? есть ли там Y-комбинатор?
— выполняет преобразования, в ходе которых создаёт концевую рекурсию, а её, в свою очередь, переводит в итерации
let iterate n f (* x *) =
    let rec iter m x =
        if m=0 then x
        else f (iter (m-1))
    in iter n (* x *)
    ;;

(*******************************)

let iterate n f (* x *) =
    let rec iter m x =
        if m=0 then x
        else iter (m-1) (f x)
    in iter n (* x *)
    ;;


Во-вторых, если не следовать заданию до последней буквы, то именно итерационную версию и можно написать
template<class F>
class iterate_n_f
{
    int n;
    F f;
public:
    iterate_n_f(int n, F f) : n(n), f(f) {}
    template<class X> X operator()(X x) const { for(int i=0; i!=n; ++i) x = f(x); return x; }
};
// карринг сделайте сами
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Функциональное программирование для всех
От: PVA  
Дата: 16.10.06 16:11
Оценка:
Lazy Cjow Rhrr,

LCR>Начну с последнего вопроса, ок?

Да, конечно. Я ведь не против прояснения деталей — за тем и пришел.

Горячая замена кода

PVA>>Сериализация не поможет?
LCR>Не поможет. Возьмём пример на Яве. Пусть у нас интерфейс CSDescriptor:
LCR>Компилируем. Меняем все зависимые от этого интерфейса классы. Компилируем. Дальше выгружаем все объекты этих классов, а также всех зависимых классов, а также всех зависимых от этих классов и т.п. на диск, пишем кастомный загрузчик (который обработает нестыковки), загружаем... Ещё что-то нужно делать со старыми потоками, а также старыми ресурсами (например, сокетами, коннекшнами к БД). Всё это контролировать настолько тяжело, что больше напоминает закат солнечной системы вручную, причём практически не отличается от перезапуска. Ну и девять девяток при таком подходе уж точно не видать...
Ужас!
Если я правильно понимаю, то ФП обладает только некоторым текущим состоянием (контекстом на входе какой-либо функции) и других зависимостей у нее нет, да? Тоесть заменить можно хоть всю программу, исключая активную функцию и ее зависимости, переданные через аргументы? (хотя, наверно, их тоже можно заменить, изменив контекст)
А как в ФЯ делается "закат солнца" автоматом?

LCR>Мне бы op_t принимающую любое количество параметров любого типа... Причём вместо создания экземпляра типа op_add я хочу просто писать (+).

Кхм, сделать-то можно, но склонен согласится с товарищем их соседнего поста с "ООП на ассемблере".

Карринг

PVA>>
#define square(x) pow((x), 2)

LCR>... а вместо создания экземпляра типа op_add_xX(2) я хочу писать (+2) (ну или (_ + 2)), вместо создания экземпляра типа op_add_Xx(2) хочу писать (2+) (или (2 + _)), а вместо создания экземпляра op_add_XX(2,3) я хочу писать 2 + 3. Ну и конечно передать полученные функции куда нибудь в ФВП.
Ненасытный какой
Приведите, пожалуйста, более полный контекст с Вашим примером.

Ленивые вычисления

PVA>>А разве оптимизаторы нынешние не делают то же самое?
LCR>Если могут — делают, но почти всегда не могут. А не могут, потому что когда вы пишете foo(x, y), то аргументы x и y должны быть вычислены до того, как управление передастся в функцию foo.
Вобщем-то, это зависит от того, чего мы хотим добиться, не так ли? x и y могут быть ссылками на объекты и вычисляться только по необходимости.

Абстрагирование от управляющих структур

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

Бесконечные структуры данных

PVA>>Шаблоны с++ + метапрограммирование?
LCR>Возможно у вас есть ещё одна свежая идея. Мне будет очень интересно.
Я имел ввиду вычисления на этапе компиляции.
Вот только что подумал что в ФП данные вычисления будут происходить в рантайме, что меняет подход к вопросу в корне.


Продолжения

PVA>>Аналогично функциям высшего порядка.
LCR>Здесь если покопать, то лес настолько дремучий, что связываться с этим не захочется. Есть реализация продолжений и на Яве, и на C, и на C#. Но все они неуниверсальны и интрузивны для клиентского кода. Поизвращаться над своим кодом я и так могу, без продолжений (тем более что "продолжения" на списках сделает любой нормальный студент, не слишком сложная задача), а что делать с rt.jar?
Не будем связываться . А что такое rt.jar?

Сопоставление с образцом

PVA>>Шаблоны?
LCR>Сопоставление с образцом уж точно не реализуемо на шаблонах. Максимум, что можно выжать, это boost::tie.
Да уж, нет в мире совершенства. А я в него так верил.

LCR>Это псевдокод. Можно было написать ещё

LCR>Function makePowerFn(int power)
LCR>{
LCR> return new Function( int powerFn(int base) { return pow (base, power); } );
LCR>}
LCR>как вариант. Но это тоже не Ява. Идея состоит в том, чтобы вернуть функцию, причём связанную с внешним параметром.
Спасибо, посыпаю голову пеплом, я пропустил, что там возвращается функиця в оригинальном примере, а так — идея ясна.

PVA>>А реализовано может быть через те же функторы.

LCR>Это вы делаете вывод исходя из ошибочного предположения, что функции высшего порядка == функторы. А на самом деле функторами можно эмулировать ФВП (так же как это делает компилятор написанный на C).
Если предположение ошибочно, то как функторами можно эмулировать ФВП?

LCR>Я с удовольствием послушаю, как вы реализуете на функторах функцию iterate:

LCR>
LCR>let compose f g x = f(g x) ;;
LCR>let rec iterate n f =
LCR>    if n = 0 then (function x -> x)
LCR>    else compose f (iterate (n-1) f) ;;

LCR>(* использовать можно так *)
LCR>let rec power i n =
LCR>    let i_times = ( * ) i in  (* "i_times n" равно функции "умножить на i" n раз *)
LCR>        iterate n i_times 1 ;;

LCR>power 2 8 ;; (* выдаст 256 *)
LCR>

(2 << 8) или power(2, 8), шутка
А можно реальный аналог подобной задачи? Думаю в ИЯ можно найти решение для нее без функторов (а может и с ними).

А еще русскоязычные обзоры/введения/и т.д. есть на просторах?
Общая картина ясна, но насколько это перспективно и в каких задачах (помимо описанных в faq, приведенном в статье)?
newbie
Re[6]: Функциональное программирование для всех
От: FR  
Дата: 16.10.06 16:57
Оценка: +1
Здравствуйте, PVA, Вы писали:


PVA>А еще русскоязычные обзоры/введения/и т.д. есть на просторах?


http://www.softcraft.ru/paradigm/dp/index.shtml

PVA>Общая картина ясна, но насколько это перспективно и в каких задачах (помимо описанных в faq, приведенном в статье)?


Даже если не будешь использовать очень полезно изучить как "взгляд с другой стороны". Это реально влияет на стиль и улучшает уровень программирования даже в чистой императивщине.
Re[7]: Функциональное программирование для всех
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 17.10.06 06:33
Оценка: +1 :)))
Здравствуйте, FR, Вы писали:

FR>Даже если не будешь использовать очень полезно изучить как "взгляд с другой стороны". Это реально влияет на стиль и улучшает уровень программирования даже в чистой императивщине.


Во многия знания многия печали. То биш стиль оно улучшит, но можит и добавить чувство неудовлетворения.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[4]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.10.06 16:37
Оценка: +1 :))) :))
Здравствуйте, PVA, Вы писали:

PVA>В свете изложенных соображений, что мешает програмить на с++ в ФП?


На С++ можно пытаться писать в функциональном стиле. Но при этом испытываешь много боли в анальном отверсии, ведь удаление гланд через зад да еще и автогеном не самая приятная процедура.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 18.10.06 02:49
Оценка:
PVA,

PVA>А как в ФЯ делается "закат солнца" автоматом?

Идеально подходит для hot upgrade динамически типизированный функциональный язык. В Practical Common Lisp есть пример, когда программу в космическом челноке исправили прямо во время полёта.

An even more impressive instance of remote debugging occurred on NASA’s 1998 Deep Space 1 mission. A half year after the space craft launched, a bit of Lisp code was going to control the spacecraft for two days while conducting a sequence of experiments. Unfortunately, a subtle race condition in the code had escaped detection during ground testing and was already in space. When the bug manifested in the wild—100 million miles away from Earth—the team was able to diagnose and fix the running code, allowing the experiments to complete.

Пример на Эрланге можно глянуть здесь
Автор: Lazy Cjow Rhrr
Дата: 01.03.06
(там парни корёжат программу во время установленного телефонного звонка). Ну если и этого мало, могу наконец дать ссылку на документацию, только это уже не так интересно

PVA>

ФВП, Карринг

PVA>Приведите, пожалуйста, более полный контекст с Вашим примером.
Пожалуйста. Вот вам задачка
Автор: Mamut
Дата: 04.03.06
от Дмитрия по операциям над изображением.
Вот решение
Автор: Трурль
Дата: 09.03.06
на Хаскеле (карринг есть).
Вот решение
Автор: Lazy Cjow Rhrr
Дата: 16.03.06
на Эрланге (карринга нет, можно только эмулировать).
Разница видна невооружённым глазом.

PVA>

Ленивые вычисления

LCR>>Если могут — делают, но почти всегда не могут. А не могут, потому что когда вы пишете foo(x, y), то аргументы x и y должны быть вычислены до того, как управление передастся в функцию foo.
PVA>Вобщем-то, это зависит от того, чего мы хотим добиться, не так ли? x и y могут быть ссылками на объекты и вычисляться только по необходимости.
Хм. Это очень жёсткие грабли, если "вычисления по необходимости" будут давать побочные эффекты (вычисления А и Б используют общую память, А пишет в общую память, Б читает, и при ленивом исполнении Б может быть вычислено раньше). Кроме того, опасны неожиданно возникающие циклы (для вычисления А нужен вычесленный Б, а для вычисления Б нужен вычисленный А). Поэтому единственный гарантированный способ избежать таких граблей — энергичное выполнение.

PVA>

Абстрагирование от управляющих структур

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

PVA>Не будем связываться . А что такое rt.jar?

Standard Runtime Library для Явы.

PVA>>>А реализовано может быть через те же функторы.

LCR>>Это вы делаете вывод исходя из ошибочного предположения, что функции высшего порядка == функторы. А на самом деле функторами можно эмулировать ФВП (так же как это делает компилятор написанный на C).
PVA>Если предположение ошибочно, то как функторами можно эмулировать ФВП?
Напрямую: функторы выступают как реализация ФВП, они инкапсулируют АСТ, реализация позволяет во время создания оптимизировать это АСТ и порождать скажем шитый код (это как бы jit-компиляции).

LCR>>
LCR>>power 2 8 ;; (* выдаст 256 *)
LCR>>

PVA>(2 << 8) или power(2, 8), шутка
Просто здесь пушка использовалась, чтобы убить муху, в то время как достаточно было мухобойки.

PVA>А можно реальный аналог подобной задачи? Думаю в ИЯ можно найти решение для нее без функторов (а может и с ними).

Любая задача, где требуется создать конструктор функций, причём возвращаемая функция будет зависеть от переданных аргументов. Интерпретатор выражений, реализация потоков (streams, которые), процессоры естественного языка, экспертные системы и т.п .

PVA>А еще русскоязычные обзоры/введения/и т.д. есть на просторах?

PVA>Общая картина ясна, но насколько это перспективно и в каких задачах (помимо описанных в faq, приведенном в статье)?
Мне очень нравится статья Сильные стороны ФП (в оригинале "Why functional programming matters") Джона Хьюгса.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[7]: Функциональное программирование для всех
От: FR  
Дата: 18.10.06 06:26
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>PVA,


PVA>>А как в ФЯ делается "закат солнца" автоматом?

LCR>Идеально подходит для hot upgrade динамически типизированный функциональный язык. В Practical Common Lisp есть пример, когда программу в космическом челноке исправили прямо во время полёта.

Динамический типизированный не функциональный язык (например clisp ) подходит для этого не хуже.
Re[8]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 18.10.06 08:01
Оценка: +1 :)
FR,

PVA>>>А как в ФЯ делается "закат солнца" автоматом?

LCR>>Идеально подходит для hot upgrade динамически типизированный функциональный язык. В Practical Common Lisp есть пример, когда программу в космическом челноке исправили прямо во время полёта.

FR>Динамический типизированный не функциональный язык (например clisp ) подходит для этого не хуже.


Ну вот, нашёл заусенчик и зацепился Хорошо, выражусь максимально на мой взгляд корректно:
Программы, написанные в функциональном и динамически типизированном стиле идеально подходят для hot upgrade.

То есть если мы будем писать на Яве, причём у нас все методы будут статические и все сигнатуры методов будут иметь вид
public static Result preved(Object[] params, public Class[] types);
public static Result medved(Object[] params, public Class[] types);

где
public class Result
{
    public Object[] params;
    public Class[] types;
}

то такие программы тоже будут идеально подходить для hot upgrade.

Какие ещё будут возражения?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[7]: Функциональное программирование для всех
От: PVA  
Дата: 18.10.06 09:47
Оценка:
Lazy Cjow Rhrr,

PVA>>А как в ФЯ делается "закат солнца" автоматом?

LCR>Идеально подходит для hot upgrade динамически типизированный функциональный язык. В Practical Common Lisp есть пример, когда программу в космическом челноке исправили прямо во время полёта.
Собственно, примеров можно придумать кучу. Меня больше интересовал технический подход к этому: как это делается в недрах с описанием на пальцах.
У меня создается ощущение, что язык скриптовый/интерпретируемый.

PVA>>

ФВП, Карринг

LCR>Разница видна невооружённым глазом.
Спа-си-ба.

PVA>>

Ленивые вычисления

LCR>>>Если могут — делают, но почти всегда не могут. А не могут, потому что когда вы пишете foo(x, y), то аргументы x и y должны быть вычислены до того, как управление передастся в функцию foo.
PVA>>Вобщем-то, это зависит от того, чего мы хотим добиться, не так ли? x и y могут быть ссылками на объекты и вычисляться только по необходимости.
LCR>Хм. Это очень жёсткие грабли, если "вычисления по необходимости" будут давать побочные эффекты (вычисления А и Б используют общую память, А пишет в общую память, Б читает, и при ленивом исполнении Б может быть вычислено раньше). Кроме того, опасны неожиданно возникающие циклы (для вычисления А нужен вычесленный Б, а для вычисления Б нужен вычисленный А). Поэтому единственный гарантированный способ избежать таких граблей — энергичное выполнение.
Хм2. Что-то здесь не совсем понятно как эти же вопросы решают ФЯ.

PVA>>

Абстрагирование от управляющих структур

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

PVA>>>>А реализовано может быть через те же функторы.

LCR>>>Это вы делаете вывод исходя из ошибочного предположения, что функции высшего порядка == функторы. А на самом деле функторами можно эмулировать ФВП (так же как это делает компилятор написанный на C).
PVA>>Если предположение ошибочно, то как функторами можно эмулировать ФВП?
LCR>Напрямую: функторы выступают как реализация ФВП, они инкапсулируют АСТ, реализация позволяет во время создания оптимизировать это АСТ и порождать скажем шитый код (это как бы jit-компиляции).
Тоесть, если нет требования к hot upgrade, то для разработчика эти понятия одинаковы? Если я правильно понял, то здесь разница как между скомпилированным кодом и скриптом.

PVA>>(1 << 8) ...

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

PVA>>А можно реальный аналог подобной задачи? Думаю в ИЯ можно найти решение для нее без функторов (а может и с ними).

LCR>Любая задача, где требуется создать конструктор функций, причём возвращаемая функция будет зависеть от переданных аргументов. Интерпретатор выражений, реализация потоков (streams, которые), процессоры естественного языка, экспертные системы и т.п .
Так большинство этих задач решается традиционно (возиожно, писать только больше приходится). А судя по качеству и количеству "процессоров естественного языка", то Х здесь не сильно помогает.

PVA>>А еще русскоязычные обзоры/введения/и т.д. есть на просторах?

PVA>>Общая картина ясна, но насколько это перспективно и в каких задачах (помимо описанных в faq, приведенном в статье)?
LCR>Мне очень нравится статья Сильные стороны ФП (в оригинале "Why functional programming matters") Джона Хьюгса.
newbie
Re[7]: Функциональное программирование для всех
От: PVA  
Дата: 18.10.06 12:01
Оценка:
Lazy Cjow Rhrr,

Интересно, что

Функциональная программа уже готова для исполнения в параллельном режиме без дополнительных модификаций. Вам не нужно беспокоиться о взаимоблокировках (deadlocks) и борьбе за ресурсы (race conditions), потому что вам просто не потребуется использовать примитивы синхронизации (locks).

LCR>

An even more impressive instance of remote debugging occurred on NASA’s 1998 Deep Space 1 mission. A half year after the space craft launched, a bit of Lisp code was going to control the spacecraft for two days while conducting a sequence of experiments. Unfortunately, a subtle race condition in the code had escaped detection during ground testing and was already in space. When the bug manifested in the wild—100 million miles away from Earth—the team was able to diagnose and fix the running code, allowing the experiments to complete.


Пример на Эрланге можно глянуть здесь (там парни корёжат программу во время установленного телефонного звонка)

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

p.s. Пошел копать в недры
newbie
Re[6]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 19.10.06 12:23
Оценка:
Кодт,

LCR>>(ocaml)

LCR>>Больше чем уверен, что вы вернёте разве что функтор-интерпретатор, который будет инкапсулировать АСТ.

К>Во-первых: а что здесь вообще можно вернуть? Какой код порождает компилятор caml?

К>- строит AST
К>- приводит к форме, свободной от переменных, т.е. к коду для комбинаторной машины — опять же, в каком базисе? есть ли там Y-комбинатор?
К>- выполняет преобразования, в ходе которых создаёт концевую рекурсию, а её, в свою очередь, переводит в итерации

Можно (в принципе) вернуть указатель на бинарный блок, полученный при компиляции (на лету) данной функции.


К>Во-вторых, если не следовать заданию до последней буквы, то именно итерационную версию и можно написать

К>
К>template<class F>
К>class iterate_n_f
К>{
К>    int n;
К>    F f;
К>public:
К>    iterate_n_f(int n, F f) : n(n), f(f) {}
К>    template<class X> X operator()(X x) const { for(int i=0; i!=n; ++i) x = f(x); return x; }
К>};
К>// карринг сделайте сами
К>


Очень интересно. Но в данном случае ты взял заботу компилятора на себя и несмотря на то, что хорошо справился (), я не думаю что этот подход разумен в общем случае.
let mk_index list_names =
    let rec make_enum a b = if a > b then [] else a :: (make_enum (a+1) b) in
    let list_index = (make_enum 0 ((List.length list_names) - 1)) in
    let assoc_index_name = List.combine list_names list_index in
        function name -> List.assoc name assoc_index_name ;;

"Функция mk_index возвращает функцию, которая принимает имя и вызывает List.assoc с этим именем и предварительно сформированным списком ассоциаций." (Пример взят из книжки "Developing apps in ocaml", пункт "Reading a database from a file").
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.