Функциональное программирование для всех
От: Линкер Николай (перевод) Россия 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<#)
Re[8]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 19.10.06 12:23
Оценка: 5 (2)
PVA,

PVA>

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

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

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

Неубедительно? Гхм. Придётся засучить рукава. Вот сделанный на коленке пример:
-module(hot).
-compile(export_all).

start() ->
    register(the_server, spawn(hot, server, [abcd])),
    register(the_client, spawn(hot, client, [0, the_server])).

stop() ->
    the_client ! stop,
    the_server ! stop.

client(N, Svr) ->
    receive
    stop ->
        io:format("client stopped~n", []),
        stop_client
    after 1000 ->
        Svr ! N,
        client(N + 1, Svr)
    end.

server(State) ->
    receive
    stop ->
        io:format("server stopped~n", []),
        stop_server;
    Msg ->
        io:format("Msg, State => ~p, ~p~n", [Msg, State]),
        hot:server(State)
    end.


Здесь запускается сервер и клиент, клиент 1 раз в секунду присылает серверу сообщение (просто целое число, каждый раз увеличивающееся на единичку). Как только сервер получает это сообщение, он распечатывает на экране полученное сообщение и состояние. Задача — на лету поменять и функцию server, и состояние. Я заменяю функцию server на
server(State) when is_atom(State) ->
    server_plus(atom_to_list(State)).

server_plus(State) ->
    receive
    stop ->
        io:format("server stopped~n", []),
        stop_server;
    Msg ->
        io:format("Msg, State >>> ~p, ~p~n", [Msg, State]),
        hot:server_plus(State)
    end.

Код заменяет старую функцию server, принимающую атом на новую функцию server_plus, принимающую список.

Ну а вот сеанс общения с оболочкой:
20> c(hot).           %%% компилируем и загружаем модуль hot
{ok,hot}
21> hot:start().      %%% запускаем функцию start в модуле hot
true
Msg, State => 0, abcd
Msg, State => 1, abcd
Msg, State => 2, abcd
Msg, State => 3, abcd
Msg, State => 4, abcd
22> c(hot).                %%% меняем функцию server
{ok,hot}
Msg, State => 5, abcd      %%% в этот момент новый код загружен
Msg, State >>> 6, "abcd"  %%% и управление передано на новую функцию server
Msg, State >>> 7, "abcd"
Msg, State >>> 8, "abcd"
Msg, State >>> 9, "abcd"
Msg, State >>> 10, "abcd"
Msg, State >>> 11, "abcd"
Msg, State >>> 12, "abcd"
Msg, State >>> 13, "abcd"
Msg, State >>> 14, "abcd"
Msg, State >>> 15, "abcd"
Msg, State >>> 16, "abcd"
Msg, State >>> 17, "abcd"
23> hot:stop().
client stopped
server stopped
stop
24>


Как видите, ловкость рук и никакого мошенничества
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[7]: Функциональное программирование для всех
От: Кодт Россия  
Дата: 19.10.06 13:03
Оценка: 1 (1) :)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Очень интересно. Но в данном случае ты взял заботу компилятора на себя и несмотря на то, что хорошо справился (), я не думаю что этот подход разумен в общем случае.

LCR>let mk_index list_names =
LCR>    let rec make_enum a b = if a > b then [] else a :: (make_enum (a+1) b) in
LCR>    let list_index = (make_enum 0 ((List.length list_names) - 1)) in
LCR>    let assoc_index_name = List.combine list_names list_index in
LCR>        function name -> List.assoc name assoc_index_name ;;

LCR>"Функция mk_index возвращает функцию, которая принимает имя и вызывает List.assoc с этим именем и предварительно сформированным списком ассоциаций." (Пример взят из книжки "Developing apps in ocaml", пункт "Reading a database from a file").

make_enum : 'a -> 'a -> ['a], энергично порождает список, никаких вложенностей здесь не нужно.
Головная рекурсия — всего лишь красивый способ записи; элементарно переделывается в хвостовую
let make_enum a b =
    let rec fwd c cs = if c > b then [] else fwd (c+1) (c::cs)
    in
    List.reverse (fwd a [])
    ;;

let make_enum a b =
    let rec rew c cs = if c < a then [] else rew (c-1) (c::cs)
    in
    (rew b [])
    ;;

В первом случае мы инвертировали конструктор списка, во втором — инвертировали всю арифметику.
И между прочим, каррингуемость её нигде не востребована: во всех двух местах (в рекурсивном определении и ниже в list_index) она применяется с обоими аргументами. Можно было передавать кортеж.
Но это неважно.
Главное, что она не конструирует рекурсивную функцию (реализация которой может быть чем-то интерпретируемым — то ли AST, то ли шитым кодом), а вычисляет законченный объект — список чисел.

Внешняя функция
let mk_index list_names name =
    let bla-bla-bla
    in
    List.assoc name assoc_index_name
    ;;

Зачем было помогать компилятору и заниматься каррингом функции mk_index вручную — не знаю.
Сама она этим не пользуется.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[8]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.10.06 07:35
Оценка: :)
Кодт,

К>make_enum : 'a -> 'a -> ['a], энергично порождает список, никаких вложенностей здесь не нужно.

К>Головная рекурсия — всего лишь красивый способ записи; элементарно переделывается в хвостовую
К> [kodt] cool analisys goes here [/kodt]


Интересный у нас разговор получается. Я говорю, что неразумно заниматься эмуляцией (оптимизацией, компиляцией) вручную ФВП на C++ и привожу пример, когда такая эмуляция требует некоторых усилий. Ты это эмулировал и даже ухом не повёл.

Ладно, привожу пример чуть сложнее, но для тебя это по-прежнему "элементарно"...

Ок. Я так полагаю, что мне надо привести пример в 83 экрана, чтобы к тебе закралась мысль "не, всё-таки на C++ это неудобно...", ы?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[8]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.10.06 10:57
Оценка: 34 (4)
PVA,

PVA>>>

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

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

Вы хотите технических деталей? Хорошо.

Математически, возможность ленивых вычислений зависит от наличия прозрачности ссылок (referential transparency), она обеспечивает то, что некое выражение будучи вычислено будет иметь тот же самый результат, независимо от того, когда оно (выражение) вычислялось и в каком порядке. Наличие прозрачности ссылок влечёт то, что любое подвыражение может быть просто заменено значением этого подвыражения. Отсюда следует, что выражение можно вычислять в другом, отличном от определения, порядке.

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

Согласно книжке Саймона Пейтона Джонса имеется 2 способа реализовать ленивые вычисления:

1. Через замыкания: замыкания представляют собой ещё не вычисленные выражения. Замыкание сохраняет в себе код выражения и биндинги для всех свободных переменных, которые встречаются в выражении. Интуитивно это звучит так: вместо передачи значения передачи значения передаётся _обещание_ вычислить значение, как только значение понадобится.

2. Через редукцию графов: этот способ требует создания "временных заморозок" (suspensions) которые включают в себя куски ещё не вычисленных графов и биндинги для свободных переменных, которые присутствуют в графе.

Более внимательный взгляд позволяет получить следующие факты (здесь отложенное вычисление — это или замыкание, или "временная заморозка"):
1. Отложенные вычисления должны существовать дольше функции, которая их создаёт, так как такое вычисление может выполниться гораздо позже того момента, как функция отработала. Отложенные вычисления ещё содержат биндинги (ссылки) на замкнутые переменные и параметры.
2. Вычисление отложенного вычисления может привести к вычислению очень глубокой рекурсии (или вообще бесконечной рекурсии, если она хвостовая), которая запросто может не влезть в стек.

Эти 2 пункта выше означают, что параметры и сами отложенные вычисления должны сохраняться в куче, а не на стеке. Как следствие это влечёт необходимость GC (который в условиях ФЯ можно сделать очень быстрым, что в общих условиях сделать проблематично, см. например здесь
Автор: Lazy Cjow Rhrr
Дата: 28.03.06
). Если ленивые вычисления эмулировать в обычных ИЯ (в которых все вызовы и параметры сохраняются на стеке), то придётся каждый вызов дублировать на куче, что дополнительно ухудшит производительность.

На практике, если аккуратно следить за зависимостями в вычислениях, то можно _чуть-чуть_ использовать ленивые вычисления в императивных языках. Но полученный воздушный замок вычислений будет довольно хрупок, потому что обеспечить прозрачную ссылочность тяжело, а разрушить легко.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[9]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.10.06 11:34
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

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


Это не на практие. Это как раз в теории. А на практике линивые вычисления в ИЯ прекрасно используются и проблем не вызвают. Просто не надо думать о всех вычислениях как о линивых.

Фактически любые стримы — это линивые вычисления. Неужели у кого-то были пролемы при чтении файла?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 21.10.06 12:25
Оценка:
VladD2, Вы писали:

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


VD>Это не на практие. Это как раз в теории. А на практике линивые вычисления в ИЯ прекрасно используются и проблем не вызвают. Просто не надо думать о всех вычислениях как о линивых.


VD>Фактически любые стримы — это линивые вычисления. Неужели у кого-то были пролемы при чтении файла?


Если одновременно писать в этот файл — будут. И вообще, я говорю про _общий_ случай, а ты указываешь на частный случай и говоришь что там всё хорошо. С тем, что всё хорошо обстоит в частных случаях (один из них — это независимые вычисления, например, чтение из потока ввода-вывода) я абсолютно согласен.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[11]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.10.06 12:59
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Если одновременно писать в этот файл — будут.


Ага, и какать за одно.
Вот этим и отличается теория от практики. На практике проблем подобного рода я что-то не встречал.


LCR>И вообще, я говорю про _общий_ случай,


А я говорю, что этот твой _общий_ — это теоретические рассуждения. А на практике люди без труда разруливают подобные ситуации.

LCR>а ты указываешь на частный случай и говоришь что там всё хорошо.


Дык практика она из частных случаев и состоит.

LCR>С тем, что всё хорошо обстоит в частных случаях (один из них — это независимые вычисления, например, чтение из потока ввода-вывода) я абсолютно согласен.


Дык я как раз и клоню к тому, что там где действительно нужна ленивость, там она неплохо работает и в ИЯ. Так что говорить, что ленивость хорошо живет только в чистых ФЯ не верно. Как не верно и то, что она вообще нужна по умолчанию.

К сожалению почти у всего в жизни есть не только хорошие стороны, но и плохие. Так и у линивости с неизменяемостью переменных есть плохие стороны. И по-моему практика показывает что в смешанных языках куда проще учитывать эти особенности вручную нежели уживаться с ограничениями и проблемами вызываемыми этими фичами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Функциональное программирование для всех
От: deniok Россия  
Дата: 21.10.06 14:41
Оценка: 1 (1) +1
Здравствуйте, VladD2, Вы писали:

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


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


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

Любой язык программирования — всегда компромисс (иногда удачный, иногда не очень). Мне кажется невозможным создание идеального языка; лучше уметь программировать на нескольких.

Похоже я утёк в философию
Re[13]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.10.06 22:53
Оценка: :)
Здравствуйте, deniok, Вы писали:

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


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

Можно, кстати, примеры задач котрые именно на Хаскеле решались бы проще, быстрее или с более производительным результатом (быстрым кодом) чем на любых других языка?

D>Любой язык программирования — всегда компромисс (иногда удачный, иногда не очень).


Ага. Вот только это банальность. Это все равно что ничего не сказать.

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


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

К тому же это все разговоры в пользу бедных. Реалии немного прозоичнее. Люди пишут не на языках которые лучше решают задачи. А на том что смогли осилить, на том что было доступно когда они что-то изучали, на том что разрекламировано, или на худой конец на том, что требовали при приеме на работу.

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

Вот и выходит, что эдакие соеденившиеся в одном флакое программисты-мечтатели-философы повторяют одни и те же мифы и банальности обсуждая приемущества языков не от мира сего (филосовских), а сами тем временем клепают софт на С++ или в лучшем случае на Яве. Понятно, что Хаскель с его оторванностью от реальной жизни ни того, ни дргого не заменит. Но, елки палки, есть же и более приближенные к жизни вещи. Да, у них фигово с комцептуальной чистоато, за-то они позволяют эффективно писать реальный код! Но похоже именно это никому и не нужно. Ведь куда прще философствовать про Хаскель и продолжать жрать кактус С++ с Явой. А то и про Оберон философию развести.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Функциональное программирование для всех
От: deniok Россия  
Дата: 22.10.06 11:20
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Можно, кстати, примеры задач котрые именно на Хаскеле решались бы проще, быстрее или с более производительным результатом (быстрым кодом) чем на любых других языка?


здесь
Автор: Кодт
Дата: 20.10.06
Re[9]: Функциональное программирование для всех
От: Кодт Россия  
Дата: 22.10.06 20:08
Оценка: +1 :)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Интересный у нас разговор получается. Я говорю, что неразумно заниматься эмуляцией (оптимизацией, компиляцией) вручную ФВП на C++ и привожу пример, когда такая эмуляция требует некоторых усилий. Ты это эмулировал и даже ухом не повёл.


LCR>Ладно, привожу пример чуть сложнее, но для тебя это по-прежнему "элементарно"...


LCR>Ок. Я так полагаю, что мне надо привести пример в 83 экрана, чтобы к тебе закралась мысль "не, всё-таки на C++ это неудобно...", ы?


Ну почему же. Я искренне недоумевал, зачем привинчивать ФВП в тех местах, где они необязательны. "Когда в моей руке молоток, то всё вокруг кажется гвоздями".
Разумеется, бывают ситуации, в которых ФВП существенно упрощают жизнь: да хотя бы обработка последовательностей (большинство из операций можно выразить с помощью fold или foldr) или монадные операции.
Но в двух предыдущих примерах...

Вот если так сформулировать вопрос: одна и та же задача более-менее равно (по количеству писанины) решается с и без ФВП. Может быть, без ФВП чуть длиннее (не в разы, а в проценты). Какие доводы за то, чтобы выбрать вариант с ФВП?
Перекуём баги на фичи!
Re: Функциональное программирование для всех
От: minorlogic Украина  
Дата: 23.10.06 11:42
Оценка: -2 :)
Мне как человеку далекому от функциональных языков очень интерессно было прочесть эту статью . Но некоторые вопросы ставят меня в тупик.

Основной это — почему некие техники программирова6ния именно в функциональном языке преподносятся как преимущества ?

Давайте сравним с какимнить языком более не менее знакомым "C".

1. Побочные эффекты и все что с ними связанно. Язык "C" совершенно не запрещает прогарммировать не используя побочные эффекты , даже наоборот , если это не необходимо то хорошим стилем считается запрет на побочные эфекты. Все остальные преимущества декларированные в статье , это использованеи в компиляторе(интерпретаторе) знание о запретах языка.

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

3. Каринг, кто запрещает ?

4. Ленивые вычисления. Нет запрета использовать в C , но нет и явных механизмов потдержки. В ФЯ тоже нет ЯВНЫХ механизмов потдержки.

5. Продолжения, это заплатка недостаткоа языка , какое же это приемущесмтво ?

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

7. Замыкания. Тут речь уже о реализации языка, технические детали.

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


Это моя беглая точка зрения , после первого прочтения. Комментированные минусы за мою ткпость велкам !
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Функциональное программирование для всех
От: Cyberax Марс  
Дата: 23.10.06 12:51
Оценка:
minorlogic wrote:
> Резюме. Язык запрещает делать очень много вещей, но за это получаем
> более бешевые реализации оптимизации, надежности и т.п. На этом
> собственно и все.
Большая часть функциональных приемов очень плохо работают без сбора
мусора. Ее в чистом С нет, так что функционально писать будет ну очень
через Ж.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[2]: Функциональное программирование для всех
От: Mamut Швеция http://dmitriid.com
Дата: 23.10.06 13:03
Оценка: 16 (2)
M>Нет запрета использовать в C , но нет и явных механизмов потдержки. В ФЯ тоже нет ЯВНЫХ механизмов потдержки.

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

M>6. Сопоставление с образцом. сахар.


И еще какой сахар! Частично смотри здесь
Автор: Mamut
Дата: 18.09.06
.

Но на самом деле... Хм. Например, вот код, генерирующий xml тэг со всеми аттрибутами (на Эрланге, естессно ):
tagStart(Tag) ->
    tagStart(Tag, []).
tagStart(Tag, Attrs) when Attrs == []->
        "<" ++ F ++ ">";
tagStart(Tag, Attrs)->
    "<" ++ F ++ " " ++ attributes(X) ++ ">".

attributes([{Key, Value}|L]) ->
    Key ++ "=\"" ++ Value ++ "\" " ++ attributes(L);
attributes([]) ->
    [].


За возможность написать

attributes([{Key, Value}|L]) ->
    %% ...


я готов продать душу любому языку программирования

Вызывается все это дело легко:
tagStart("myTag", [
                    {"attr", "key"},
                    {"attr2", "key2"}
                  ])


И оно выдает
<myTag attr="key" attr2="key2">



Ну или например, функции высшего порядка и сопоставление с образцом.

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

В следующих примерах нас интересует реализация функции myFunc.

Реализация без ФВП и сопоставления (JavaScript):

function some_func(X)
{
    return X*2;
}

function myFunc(args) /*args - массив данных*/
{
    arr = new Array;
    for(i = 0; i < args.length; i++)
    {
        arr.push(some_func(args[i]));
    }
    
    return arr;
}


В чем минус? в том, что этот цикл надо писать каждый раз. А это — три-четыре строчки ненужного кода.

Теперь с функциями высшего порядка. Опять JavaScript:
function some_func(X)
{
    return X*2;
}

function map(Func, Arr)
{
    arr = new Array;
    
    for(i = 0; i < args.length; i++)
    {
        arr.push(Func(args[i]));
    }
    
    return arr;
}

function myFunc(args)
{
    return map(some_func, args);
}


Теперь, если функция map у нас подключается всегда, то все функции типа myFunc будут реализовываться в одну строчку.

А теперь смертельный номер! Реализация функции map с помощью сопоставления с образцом. Erlang:
map(Func, []) -> [];
map(Func, [Head|Tail]) -> Func(Head) ++ map(Func, Tail).


++ — это конкатенация массивов. Остальное понятно без слов

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

M>Резюме. Язык запрещает делать очень много вещей, но за это получаем более бешевые реализации оптимизации, надежности и т.п. На этом собственно и все.


Оптимизации — возможно. Надежности — очень и очень спорно. Надежность зачастую не от языка программирования зависит
... << RSDN@Home 1.2.0 alpha rev. 655>>


dmitriid.comGitHubLinkedIn
Re[2]: Функциональное программирование для всех
От: Quintanar Россия  
Дата: 23.10.06 14:57
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>1. Побочные эффекты и все что с ними связанно. Язык "C" совершенно не запрещает прогарммировать не используя побочные эффекты , даже наоборот , если это не необходимо то хорошим стилем считается запрет на побочные эфекты. Все остальные преимущества декларированные в статье , это использованеи в компиляторе(интерпретаторе) знание о запретах языка.


Вы плохо понимаете, что такое побочные эффекты. Если вы меняете поле в структуре, которую вам передали по указателю, то вы меняете состояние внешнего объекта — это побочный эффект. А программ на С, где такого нет, я не знаю.

M>2. Функции высшего порядка , каждется очень мало языков , где не было бы их аналога в том или ином виде ?


Да прям? Реально таких языков (императивных) очень мало.

M>3. Каринг, кто запрещает ?


Никто. Писанина только лишняя нужна.

M>4. Ленивые вычисления. Нет запрета использовать в C , но нет и явных механизмов потдержки. В ФЯ тоже нет ЯВНЫХ механизмов потдержки.


Есть (это даже не вспоминая о ленивых языках). Если у нас есть анонимные функции и замыкания, ленивость сравнительно легко эмулировать.

M>5. Продолжения, это заплатка недостаткоа языка , какое же это приемущесмтво ?


Каких, интересно, недостатков? Продолжения — это очень мощный механизм контроля за ходом выполнения программы. Это языки, где их нет, используют заплатки для эмуляции.

M>6. Сопоставление с образцом. сахар.


Если вы только не фанат многокилометровых if-ов с постоянными проверками существования объектов. Так можно и классы в С++ сахаром объявить. Пацаны легко могут таблицы виртуальных функций руками создавать.

M>7. Замыкания. Тут речь уже о реализации языка, технические детали.


Нифига себе техническая деталь. Да это, собственно, основа функционального подхода. Это настолько полезный и мощный механизм, что его начали включать уже даже в mainstream языки.
Re[2]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.10.06 19:47
Оценка: :)
Здравствуйте, minorlogic, Вы писали:

M>Это моя беглая точка зрения , после первого прочтения. Комментированные минусы за мою ткпость велкам !


По просбам трудящийся поставил минус.

И что немало важно от души.

Аргументирую так. Ты не знаешь о чем говоришь. Поробуй, а потом еще раз выскажись. Уверен, что твое мнение сильно изменится.

ЗЫ

Думаю самую плохую услугу ФП оказывают его популяризаторы. Они перегибают палку часто доводя рекламу ФП до уровня рекламы гебалайфа.

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

Продолжения это вообще мега-фича только вот к ФП в общем-то не относящаяся. В прочем ФП вообще илюзорен. Это набор паттернов кторый можно без проблем применять в ИЯ. Основное достоинство ФЯ заключается в том, что они резко упрощают использование этого стиля.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.10.06 20:33
Оценка:
Здравствуйте, Quintanar, Вы писали:

Q>Вы плохо понимаете, что такое побочные эффекты. Если вы меняете поле в структуре, которую вам передали по указателю, то вы меняете состояние внешнего объекта — это побочный эффект. А программ на С, где такого нет, я не знаю.


Это зависит исключительно от того кто и как пишет.

M>>2. Функции высшего порядка , каждется очень мало языков , где не было бы их аналога в том или ином виде ?


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

Q>Да прям? Реально таких языков (императивных) очень мало.


Почти все.

M>>3. Каринг, кто запрещает ?


Q>Никто. Писанина только лишняя нужна.


Смешно только то, что основная масса ФЯ не поддерживает карритнг. И что характирно не сильно от этого страдает.

M>>4. Ленивые вычисления. Нет запрета использовать в C , но нет и явных механизмов потдержки. В ФЯ тоже нет ЯВНЫХ механизмов потдержки.


Q>Есть (это даже не вспоминая о ленивых языках). Если у нас есть анонимные функции и замыкания, ленивость сравнительно легко эмулировать.


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

Реальность же прозаична. Ленивость есть в языках которые мало применяются на практике. А в успешных ФЯ ее почему-то прпактически нет. Эмуляция как уже сказано не всчет. Да и можно глянуть на разные Руби и Шарпы где есть yiald со всеми вытекающими.

M>>5. Продолжения, это заплатка недостаткоа языка , какое же это приемущесмтво ?


Q>Каких, интересно, недостатков? Продолжения — это очень мощный механизм контроля за ходом выполнения программы. Это языки, где их нет, используют заплатки для эмуляции.


Вот тут полностью согласен. Дейтвительно мощьная вещь. Жалоко что эффектино реализвать ее для компилируемого языка не просто (я не видел 100%-но универсальной реализации). Да и опять же никакого отношения в ФЯ. Руби тому прямое подтверждение.

M>>6. Сопоставление с образцом. сахар.


Q>Если вы только не фанат многокилометровых if-ов с постоянными проверками существования объектов. Так можно и классы в С++ сахаром объявить. Пацаны легко могут таблицы виртуальных функций руками создавать.


Согласен. Если не вдаваться в философию на тему что такое сахар, то ежу очевидно, что чем проще писать ная зыке (и соотвествнно читать), тем лучше. А значит такой сахар и есть пвышение уровня языка и его вразительности.

M>>7. Замыкания. Тут речь уже о реализации языка, технические детали.


Q>Нифига себе техническая деталь. Да это, собственно, основа функционального подхода. Это настолько полезный и мощный механизм, что его начали включать уже даже в mainstream языки.


И тем не менее замыкания прекрасно живут в императивном языке. Но это поять вопрос философский — "что считать ФЯ?".
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.10.06 20:33
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Но на самом деле... Хм. Например, вот код, генерирующий xml тэг со всеми аттрибутами (на Эрланге, естессно ):

M>
M>tagStart(Tag) ->
M>    tagStart(Tag, []).
M>tagStart(Tag, Attrs) when Attrs == []->
M>        "<" ++ F ++ ">";
M>tagStart(Tag, Attrs)->
M>    "<" ++ F ++ " " ++ attributes(X) ++ ">".

M>attributes([{Key, Value}|L]) ->
M>    Key ++ "=\"" ++ Value ++ "\" " ++ attributes(L);
M>attributes([]) ->
M>    [].
M>


А откуда взялся F (выделено жирным)?

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

Вот высокопроизводительный аналогичный примен на более продвинутом языке :
using System.Console;

def tagStart(tag, attrs = [])
{
  | (tag, [])    => $"<$tag>"
  | (tag, attrs) => $"<$tag$(attributes(attrs))>"
}
and attributes(attrs)
{
  | (key, value) :: tail => $" $key='$value'$(attributes(tail))"
  | []                   => ""
} 

WriteLine(tagStart("SimpleTeg"));
WriteLine(tagStart("TegWithAttributes", [("attr", "key"), ("attr2", "key2")]));

Код выводит:
<SimpleTeg>
<TegWithAttributes attr='key' attr2='key2'>


M>За возможность написать

M>
M>attributes([{Key, Value}|L]) ->
M>    %% ...
M>

M>я готов продать душу любому языку программирования

Да, паттерн-матчинг это иногда очень удобно. Вот только боюсь, что твой оппонент так и не понял, что ты пытался ему показать. Советую написать аналогичный код на C/C++. Хотя, думаю, такой примитив не даст особого выигрыша.

Вот только данный пример на http://www.stringtemplate.org/ выглядит несколько лучше.

M>В следующих примерах нас интересует реализация функции myFunc.


M>Реализация без ФВП и сопоставления (JavaScript):

M>[code]

M>function some_func(X)

M>{
M> return X*2;
M>}
...
M>Таким образом, то что требует от нас десятки строк на других языках, на языках с явной поддержкой всего это "сахара" выливается в очень компактный и намного более понятный код.

Ага. Толкьо примеры слшком примитивные. И сотвествнно выигрыш мало заметен.

ЗЫ

Да! И что на счет таких "неотемлемых приемуществ ФЯ" как каринг и ленивость?

По-моему — это натуранльный фанатизм. Отдельные фичи приписываются парадигме чтобы показать ее превосходство.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Функциональное программирование для всех
От: Mamut Швеция http://dmitriid.com
Дата: 24.10.06 07:16
Оценка:
M>>Но на самом деле... Хм. Например, вот код, генерирующий xml тэг со всеми аттрибутами (на Эрланге, естессно ):
M>>
M>>tagStart(Tag) ->
M>>    tagStart(Tag, []).
M>>tagStart(Tag, Attrs) when Attrs == []->
M>>        "<" ++ F ++ ">";
M>>tagStart(Tag, Attrs)->
M>>    "<" ++ F ++ " " ++ attributes(X) ++ ">".

M>>attributes([{Key, Value}|L]) ->
M>>    Key ++ "=\"" ++ Value ++ "\" " ++ attributes(L);
M>>attributes([]) ->
M>>    [].
M>>


VD>А откуда взялся F (выделено жирным)?


Сорри Забыл заменить

VD>Вот только данный пример на http://www.stringtemplate.org/ выглядит несколько лучше.


Где? А то я смотрю в книгу и вижу известно что

M>>Таким образом, то что требует от нас десятки строк на других языках, на языках с явной поддержкой всего это "сахара" выливается в очень компактный и намного более понятный код.


VD>Ага. Толкьо примеры слшком примитивные. И сотвествнно выигрыш мало заметен.


Ну, не приводить же сразу какой-нибудь ErlyDB

VD>ЗЫ


VD>Да! И что на счет таких "неотемлемых приемуществ ФЯ" как каринг и ленивость?


В каринг я пока не въехал, поэтому говорить о нем ничего не буду А ленивость я только в Хаскеле и видел. Идея интересная, но на практике не понятно, как применяемая (для меня непонятная, естессно).

Так что из ФЯ я для себя вынес только стойкую привязанность к ФВП и сопоставлению с образцом

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


Возможно
... << RSDN@Home 1.2.0 alpha rev. 655>>


dmitriid.comGitHubLinkedIn
Re[5]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.10.06 09:09
Оценка: 16 (2)
Здравствуйте, Mamut, Вы писали:

M>>>Но на самом деле... Хм. Например, вот код, генерирующий xml тэг со всеми аттрибутами (на Эрланге, естессно ):

M>>>
M>>>tagStart(Tag) ->
M>>>    tagStart(Tag, []).
M>>>tagStart(Tag, Attrs) when Attrs == []->
M>>>        "<" ++ F ++ ">";
M>>>tagStart(Tag, Attrs)->
M>>>    "<" ++ F ++ " " ++ attributes(X) ++ ">".

M>>>attributes([{Key, Value}|L]) ->
M>>>    Key ++ "=\"" ++ Value ++ "\" " ++ attributes(L);
M>>>attributes([]) ->
M>>>    [].
M>>>


VD>>Вот только данный пример на http://www.stringtemplate.org/ выглядит несколько лучше.


M>Где? А то я смотрю в книгу и вижу известно что


Вот это почитай http://www.antlr.org/wiki/display/ST/StringTemplate+3.0+Documentation
За точность не ручаюсь, но код будет примерно таким:
tagStart(tag, attrs) ::= <$tag$ $attrs:{ key, val | $key$="$val$" }; separator=", "$>

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

Я вот в будущем собираюсь прикрутить к Немерлу подобную фишку.

M>Ну, не приводить же сразу какой-нибудь ErlyDB


Это конечно лишнее. Но и на таких примерах народ мало что поймет.

VD>>Да! И что на счет таких "неотемлемых приемуществ ФЯ" как каринг и ленивость?


M>В каринг я пока не въехал, поэтому говорить о нем ничего не буду А ленивость я только в Хаскеле и видел. Идея интересная, но на практике не понятно, как применяемая (для меня непонятная, естессно).


Я вообще-то намекал на то, что в Эрлэнге нет ни того, ни дргого. В том смысле что к ФЯ они имеют овершенно косвенное отношение. Хотя вещи удобные. В Немерле вместо каринга есть частичное применение функций, а ленивость реализована макросом. Так что можно сказать, что у этих фич есть аналоги.

M>Так что из ФЯ я для себя вынес только стойкую привязанность к ФВП и сопоставлению с образцом


Ну, вот образцы тоже к ФП отношения не имеют. Просто их впервые применили в ФЯ (и пока что только в них). Но рано или поздно они попатуд в языки кторые ФЯ назвать будет тяжело. Причем именно потому, что действительно удобная вещь.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Функциональное программирование для всех
От: deniok Россия  
Дата: 24.10.06 09:53
Оценка:
Здравствуйте, Mamut, Вы писали:

M> А ленивость я только в Хаскеле и видел. Идея интересная, но на практике не понятно, как применяемая (для меня непонятная, естессно).


Ну, можно задавать бесконечные конструкции. Например, монтируем бесконечный список простых чисел, используя решето Эратосфена
primes = sieve [2 .. ]   
sieve (x:xs) = x : sieve [y | y <- xs, (y `rem` x) /= 0]

а затем пользуемся необходимым кусочком:
take 10 primes 
-- вернёт [2,3,5,7,11,13,17,19,23,29]

Без "ленивости" обращение к primes вело бы к весьма долгому ожиданию .
Re[5]: Функциональное программирование для всех
От: Quintanar Россия  
Дата: 24.10.06 10:19
Оценка:
Ленивость упрощает логику программы — граничные условия можно опускать.
Вот числа фибоначи, например, можно считать не думая о том, сколько элементов понадобиться и поэтому программа становиться совсем простой:
fib = 1:1:(list_merge (+) fib (tail fib))

list_merge f [a] [b] -> [f a b] — не помню, как в Haskell такая функция называется.
Re[6]: Функциональное программирование для всех
От: Programmierer AG  
Дата: 24.10.06 10:26
Оценка:
Quintanar wrote:
> list_merge f [a] [b] -> [f a b] — не помню, как в Haskell такая функция называется.
zipWith
Posted via RSDN NNTP Server 2.0
Re[6]: Функциональное программирование для всех
От: deniok Россия  
Дата: 24.10.06 10:30
Оценка:
Здравствуйте, Quintanar, Вы писали:

Q>list_merge f [a] [b] -> [f a b] — не помню, как в Haskell такая функция называется.


zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Re[3]: Функциональное программирование для всех
От: deniok Россия  
Дата: 24.10.06 12:12
Оценка: 3 (3) +1
Здравствуйте, VladD2, Вы писали:


VD>Продолжения это вообще мега-фича только вот к ФП в общем-то не относящаяся. В прочем ФП вообще илюзорен. Это набор паттернов кторый можно без проблем применять в ИЯ.


Класс ! Продолжу редукцию:

Программирование вообще иллюзорно. Это набор паттернов, который можно без проблем применять.


VD>Основное достоинство ФЯ заключается в том, что они резко упрощают использование этого стиля.


Ну о том и речь!

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

В чистых ИЯ работа с состояниями — как воздух (никто и не замечает). Зато подпорки нужны для отложенных вычислений.

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

Но у чистых ФЯ есть важная особенность: для них возможны формально-математический анализ и формально-математическое манипулирование. Это приводит к тому, что в их мире рождаются идеи, которые позже внедряются в прочие языки. Яркий пример этого — автоматический вывод типов.
Re[10]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 25.10.06 12:50
Оценка:
Кодт,

К>Ну почему же. Я искренне недоумевал, зачем привинчивать ФВП в тех местах, где они необязательны. "Когда в моей руке молоток, то всё вокруг кажется гвоздями".

К>Разумеется, бывают ситуации, в которых ФВП существенно упрощают жизнь: да хотя бы обработка последовательностей (большинство из операций можно выразить с помощью fold или foldr) или монадные операции.
К>Но в двух предыдущих примерах...

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

Когда мы сравниваем 2 языка на скорость и выбираем некоторый тест, например alphablend, считается некорректным приводить другой алгоритм, не так ли (отбросим философский вопрос о нужности таких сравнений )? А здесь такое же сравнение, только на выразительность.

К>Вот если так сформулировать вопрос: одна и та же задача более-менее равно (по количеству писанины) решается с и без ФВП. Может быть, без ФВП чуть длиннее (не в разы, а в проценты). Какие доводы за то, чтобы выбрать вариант с ФВП?


Меньше сущностей — больше ясность — гармоничнее гармония!
Вместо делегатов, колбасок (callbacks), функторов, эмуляторов лямбд, стратегий, композитов с декораторами использовать только ФВП — разве плохо?

Но если вернуться к разговору о C++... Как мы можем в C++ выбрать вариант с ФВП? Мы можем выбрать вариант с loki:functor, boost:function или своей реализацией function, что нибудь типа
  template<typename Function> // function type R (T1, T2, ..., TN),
  class function 
    : public unary_function<R, T1> // iff N == 1
    : public binary_function<R, T1, T2> // iff N == 2
  {
  public:
    typedef R result_type;
        ...
    R operator()(T1, T2, ..., TN) const;
  };

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

Последний пример.
Можно в принципе подумать как написать на C++ аналог Parsec (или другой библиотеки комбинаторов). Но сомневаюсь, что это будет так же красиво для пользователя. (И сомневаюсь, что будет просто).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[11]: Функциональное программирование для всех
От: Programmierer AG  
Дата: 25.10.06 12:55
Оценка: 1 (1)
> Можно в принципе подумать как написать на C++ аналог Parsec (или другой библиотеки комбинаторов). Но сомневаюсь, что это будет так же красиво для пользователя. (И сомневаюсь, что будет просто).
Ну, это как раз давно есть —
Boost.Spirit.

Само собой, не так же красиво и не так просто .
Posted via RSDN NNTP Server 2.0
Re[4]: Функциональное программирование для всех
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 25.10.06 19:19
Оценка: 1 (1) :)))
Здравствуйте, deniok, Вы писали:

D>Я заранее соглашусь с тем, что для большинства программистов и большинства (но не подавляющего) задач ИЯ — то, что доктор прописал. И что есть весьма симпатичные смешанные языки, и среди них есть очень-очень симпатичный смешанный язык.


Э-э-э... Лисп?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.10.06 10:27
Оценка:
Здравствуйте, deniok, Вы писали:

D>Программирование вообще иллюзорно. Это набор паттернов, который можно без проблем применять.


Это уже софистика.

VD>>Основное достоинство ФЯ заключается в том, что они резко упрощают использование этого стиля.


D>Ну о том и речь!


D>В чистых ФЯ легко работать с отложенными вычислениями, полагаясь на прозрачность ссылок и ленивость. Зато для работы с состояниями требуются подпорки. Например, монады.


Во, во. Костыли для исправления извращений мозга.
Реально ленивость в повседневной жизни нужна крайне редко. И где она действительно нужна легко достигается. На то есть всягого рода потоки, итераторы, ссылочные объекты, замыкания... А вот повсеместная ленивость приводит к геморою. Отладка резко усложняется (ести про ее ненужность отавим тем кто никогда не писал сложный код). Компиляция получаеся неполноценной (код тормозит). Незнаю уж связано ли это слинивостью (думаю — да), но повяляются всякого рода монады и другие извращения резко усложняющие понимание казалось бы простых вещей.

Если поглядить на реалии жизни, то вдино, что большинство те же ФЯ не являются линивыми, а так называемые "чистые" ФЯ реально на практике используются крайне редко (и вообще пратически ограничиваются Хаскелем).

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

D>Я заранее соглашусь с тем, что для большинства программистов и большинства (но не подавляющего) задач ИЯ — то, что доктор прописал. И что есть весьма симпатичные смешанные языки, и среди них есть очень-очень симпатичный смешанный язык.


Это тут не причем. Меня всегда радовал тот радикализм и извращение фактов которые используются при пропагадне (другого слова не подберу) ФЯ. Вот стериотип о том что ФЯ == линивые вычисления и что линивые вычисления это несомненное достоинство как раз проявление этого. Достаточно включить логику и немного удалиться от веры в слова проповедников, чтобы понять, что линивость всего лишь свойство языка. Не более, и не менее. От него есть польза, а есть вред. Далее не составит труда понять, что те кто отказываается от линивости просто считают вред куда большим нежели пользу.

D>Но у чистых ФЯ есть важная особенность: для них возможны формально-математический анализ и формально-математическое манипулирование. Это приводит к тому, что в их мире рождаются идеи, которые позже внедряются в прочие языки. Яркий пример этого — автоматический вывод типов.


Чущь это. Опять же инсперированная рекламными лозунгами пропагаднистов ФЯ. Формальные методы анализа есть для любоко ЯП. Более того любоая программа может быть переписана с ФС в ИС и обратно. Вся разница заключается в возможности изменить пременную. Это несомненно несколько усложняет анализ программ, но отнюдь не делает его невозможным.

Господа, разуйте глаза. Лучшие оптимзирующие компиляторы созданы для императивных языков самого низкого качества — С, С++ и Фортрана. В них не только есть побочные эффекты, но и ужасные указатели в сочетении с goto. И как не странно они лидеры в генерации высокопроизводительного кода.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Функциональное программирование для всех
От: deniok Россия  
Дата: 26.10.06 13:26
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Это тут не причем. Меня всегда радовал тот радикализм и извращение фактов которые используются при пропагадне (другого слова не подберу) ФЯ. Вот стериотип о том что ФЯ == линивые вычисления и что линивые вычисления это несомненное достоинство как раз проявление этого. Достаточно включить логику и немного удалиться от веры в слова проповедников, чтобы понять, что линивость всего лишь свойство языка. Не более, и не менее. От него есть польза, а есть вред. Далее не составит труда понять, что те кто отказываается от линивости просто считают вред куда большим нежели пользу.


Где те проповедники, которые утверждали, что "ФЯ == линивые вычисления"? Давай вместе на них набросимся . Если уж тебе нужен лозунг для оспаривания, то пожалуйста:

ФП — это отсутствие побочных эффектов.

D>>Но у чистых ФЯ есть важная особенность: для них возможны формально-математический анализ и формально-математическое манипулирование. Это приводит к тому, что в их мире рождаются идеи, которые позже внедряются в прочие языки. Яркий пример этого — автоматический вывод типов.


VD>Чущь это. Опять же инсперированная рекламными лозунгами пропагаднистов ФЯ. Формальные методы анализа есть для любоко ЯП. Более того любоая программа может быть переписана с ФС в ИС и обратно. Вся разница заключается в возможности изменить пременную. Это несомненно несколько усложняет анализ программ, но отнюдь не делает его невозможным.


Ага. Только в чистых ФЯ формальные методы анализа максимально просты с математической точки зрения. Алгоритм Милнера проверки типа, например, мог родится только в мире ФП. Сейчас автоматический вывод типов внедряется в другие языки (в той или иной степени усечённости). Так что речь идёт не о рекламных лозунгах, а об исторических фактах.
Re[6]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.10.06 14:34
Оценка:
Здравствуйте, deniok, Вы писали:

D>Где те проповедники, которые утверждали, что "ФЯ == линивые вычисления"?


Они везде. Оглянись. То тут, то там постоянно слышишь, о ленивости как о приемуществе ФП.

D>Давай вместе на них набросимся .


Присоеденяйся. Я этим занимаюсь последние два года.

D>Если уж тебе нужен лозунг для оспаривания, то пожалуйста:


Мне не нужны лозунги. Но их ахинею я слушать не намерен.

D>ФП — это отсутствие побочных эффектов.


Это тоже ахинея. Весь смысл работы компьютеров — это побочные эффекты. И любой ЯП содержит средсва для их организации. Как в прочем почти любой язык позволят писать программы без них.

Так что разумно будте сказать, что ФП — это стиль программирования в котором предпочтительным является минимизация побочных эффектов.

D>Ага. Только в чистых ФЯ формальные методы анализа максимально просты с математической точки зрения.


Скажем так "выглядт проще". Но это ни на что не влияет. Если уж так подумать, то проще всего анализировать программу на БрэйнФаке. Но что с того толку?

D>Алгоритм Милнера проверки типа, например, мог родится только в мире ФП.


С чего бы это? Очередной пример неверной логики.

D>Сейчас автоматический вывод типов внедряется в другие языки (в той или иной степени усечённости).


Это алгоритм Милнера скорее усеченный. Что и позволило реализовать его на старом железе и без невероятных затрат. Вот только это опять таки ничего не говорит.

Кстати, напомню, что этот самый алгоритм применяется в ОКамле — гибридном языке поддерживающем ИП.

D>Так что речь идёт не о рекламных лозунгах, а об исторических фактах.


Речь идет о грубейщих ошибках в логике. Неумении делать примитивные логические выводы. И в отвроенном притягивании аргументов за ущи.

Большинство фанатов ФЯ защищающих их даже не могут сойтись во мнении по вопросу что же такое ФЯ. Для одних это отсуствие модификации перменных, другие притягивают сюда ленивость, и т.д., и т.п. Так что остается только передать горячий привет Элрангу, Лиспу и всем клонам ML-я которые никак не подпадают под их определение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Функциональное программирование для всех
От: deniok Россия  
Дата: 26.10.06 16:15
Оценка: +1
Здравствуйте, VladD2, Вы писали:

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


D>>Где те проповедники, которые утверждали, что "ФЯ == линивые вычисления"?


VD>Они везде. Оглянись. То тут, то там постоянно слышишь, о ленивости как о приемуществе ФП.


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

VD>Так что разумно будте сказать, что ФП — это стиль программирования в котором предпочтительным является минимизация побочных эффектов.


OK. Согласен в практическом аспекте.

D>>Алгоритм Милнера проверки типа, например, мог родится только в мире ФП.


VD>С чего бы это? Очередной пример неверной логики.


В мире ИЯ идея полностью автоматического вывода не возникала, поскольку
// C++
void do_smth(PolymorficBaseType& p)
{
    // какой тип имеет объект р?

    SomeType s("Вася", 33); // догадается без SomeType ?

    unsigned int q = 3; // догадается без unsigned int ?
}

(и это не только из-за фич С++ ). Поскольку идея оказалась хороша, дизайн современных языков, где её хотят использовать делают таким, чтобы вывод типов был допустим в максимальном числе мест.

D>>Сейчас автоматический вывод типов внедряется в другие языки (в той или иной степени усечённости).


VD>Это алгоритм Милнера скорее усеченный. Что и позволило реализовать его на старом железе и без невероятных затрат. Вот только это опять таки ничего не говорит.


Не мучай термин "усечённый". Алгоритм Милнера естественно расширяют, чтобы довести до практической реазизации в конкретном языке. Я же, применяя этот термин, имел в виду, что в чистом ФЯ допустим полностью автоматический статический вывод типов. В ИЯ и смешанных языках есть ситуации, где тип указывать необходимо.
Re[8]: Функциональное программирование для всех
От: VoidEx  
Дата: 26.10.06 23:32
Оценка:
Здравствуйте, deniok, Вы писали:

D>В мире ИЯ идея полностью автоматического вывода не возникала, поскольку

D>
D>// C++
D>void do_smth(PolymorficBaseType& p)
D>{
D>    // какой тип имеет объект р?

D>    SomeType s("Вася", 33); // догадается без SomeType ? // А что мешает догадаться? Вот чисто теоретически

D>    unsigned int q = 3; // догадается без unsigned int ? // Аналогично
D>}
D>
Re[9]: Функциональное программирование для всех
От: deniok Россия  
Дата: 27.10.06 04:40
Оценка: -1
Здравствуйте, VoidEx, Вы писали:

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


D>>В мире ИЯ идея полностью автоматического вывода не возникала, поскольку

D>>
D>>// C++
D>>void do_smth(PolymorficBaseType& p)
D>>{
D>>    // какой тип имеет объект р?

D>>    SomeType s("Вася", 33); // догадается без SomeType ? // А что мешает догадаться? Вот чисто теоретически

D>>    unsigned int q = 3; // догадается без unsigned int ? // Аналогично
D>>}
D>>


Ты смайлик не забыл?
Если нет, догадывайся, каков тип q:
// auto предлагается в C++0x использовать для указания того, что тип выводится автоматически
// ниже, конечно, псевдо-С++: 
auto foo()
{
    auto q(7, 22.3); 
    return q;
}


То есть ответ-то есть: тип с конструктором cons(int,double). Только что с этим обобщённым типом потом делать? Это не шаблонная (в смысле template) обобщенность.
Re[8]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 07:59
Оценка:
Здравствуйте, deniok, Вы писали:

D>Это свойство. Легко реализуемое, благодаря отсутствию побочных эффектов.


Попробуй доказать, что это свойство не реализуется в языках с побочными эффектами.
Так же попробуй объяснить почему в чисто императивных языках вроде C# или Ruby прекрасно работают в полностью ленивом режиме такие вещи как итераторы и континюэшоны.

Вот если сможешь это доказать и объяснить, то можно будте о чем-то поговориь. А так как доказать это физически невомзожно, то предлагаю больше не поторять это ошибочное мнение.


D>В мире ИЯ идея полностью автоматического вывода не возникала,


Идея вообще возникла только в ограниченом числе языков. Факт что есть языки с побочными эффектами выводящие типы. Так что это очередное свидетелство неверной логики.

D>поскольку

D>
D>// C++
D>void do_smth(PolymorficBaseType& p)
D>{
D>    // какой тип имеет объект р?

D>    SomeType s("Вася", 33); // догадается без SomeType ?

D>    unsigned int q = 3; // догадается без unsigned int ?
D>}
D>


Извни, ты точно понимаешь принципы вывода типов или просто слылаш о Хндли-Миллере?
Если написать:

def do_smth(p)
{
  def s("Вася", 33)
  def q = 3;
}

то ни один супер язык не выведет типы верно. И С++ тут не причем. В этом коде банально нехватает информации.


D>(и это не только из-за фич С++ ).


Что "это"?

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


Извини, но с этим высказыванием даже спорить нельзя. Нет ни одного языка с выводом типов который смог бы выводить типы в любых ситуациях. Все они имеют необязательное аннотирование типов. Проблематичность же и сложность вывода типов зависить исключительно от сложности системы типов и мудрености алгоритма. Хиндли-Миллер очень примитивна система типов потому она и позволяет отностилеьно лекго выводить типы. При этом она вводит море ограничений. НО!!! Она не имеет к функциональному программированию никакого отношения. Без каких либо проблем можно построить императивный язык с этой ситемой типов. Собственно ОКамл, например, яляется иммеративным языком. В нем есть возможность менять переменные. И система типов ему никак н мешает.

В общем, потрудись обосновать и это заявление. Уверен, что и это не удастся.

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


Обоснуй.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 08:02
Оценка:
Здравствуйте, deniok, Вы писали:

D>Ты смайлик не забыл?

D>Если нет, догадывайся, каков тип q:
D>
D>// auto предлагается в C++0x использовать для указания того, что тип выводится автоматически
D>// ниже, конечно, псевдо-С++: 
D>auto foo()
D>{
D>    auto q(7, 22.3); 
D>    return q;
D>}
D>


D>То есть ответ-то есть: тип с конструктором cons(int,double). Только что с этим обобщённым типом потом делать? Это не шаблонная (в смысле template) обобщенность.


Пример, на любом ФЯ приведи где тебя компилятор не пошлет.

Это же просто обсурд что ты говришь!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Функциональное программирование для всех
От: ie Россия http://ziez.blogspot.com/
Дата: 27.10.06 08:02
Оценка:
Здравствуйте, deniok, Вы писали:

D>Если нет, догадывайся, каков тип q:

D>
D>auto foo()
D>{
D>    auto q(7, 22.3); 
D>    return q;
D>}
D>


Если не отрывать от контекста использования, то вполне можно догадаться.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Превратим окружающую нас среду в воскресенье.
Re[8]: Функциональное программирование для всех
От: Кодт Россия  
Дата: 27.10.06 08:44
Оценка: 1 (1) +1
Здравствуйте, deniok, Вы писали:

D>В мире ИЯ идея полностью автоматического вывода не возникала, поскольку

D>
D>// C++
D>void do_smth(PolymorficBaseType& p)
D>{
D>    // какой тип имеет объект р?

D>    SomeType s("Вася", 33); // догадается без SomeType ?

D>    unsigned int q = 3; // догадается без unsigned int ?
D>}
D>

D>(и это не только из-за фич С++ ). Поскольку идея оказалась хороша, дизайн современных языков, где её хотят использовать делают таким, чтобы вывод типов был допустим в максимальном числе мест.

В С++ свой подход к типизации, однонаправленный (т.е., зная тип аргументов, можно вывести тип результата).
К императивности отношения не имеет вообще. Хотя бы потому, что этот подход распространяется и на язык шаблонов (чисто декларативный), в котором вообще царит утиная типизация.

Почему в С++ типизация однонаправленная, а не двунаправленная (Хиндли-Милнера), или не вообще утиная? Ну вот так исторически оказалось удобнее. Причём заметь: не компилятору удобнее, а программисту: дешёвый полиморфизм без головной боли даже об арности. (Упражнение: напишите на *ML printf не в виде макроса, а в виде функции. Замучаетесь и обломитесь!)
В Лиспе типизация утиная, а ведь тоже ФЯ...
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[7]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 27.10.06 09:22
Оценка: 12 (1) +4 :)))
VladD2,

D>>Давай вместе на них набросимся .

VD>Присоеденяйся. Я этим занимаюсь последние два года.

О, да, известный Борец-С-Ветряными-Мельницами.
В чём смысл борьбы то? Борьба с неверными () али движение за мировое господство "ТхеРигхтТхинга" ()?

В принципе я бы мог потратить время и ответить подробно, с примерами и пояснениями (btw, строгого доказательства в принципе сделать невозможно, поскольку речь идёт о человеке и вопрос "легче/труднее" часто субъективен и неформален), почему с ростом сложности систем сложность реализации ленивых вычислений в условиях mutable state растёт экспоненциально, но увы, после таких доводов

VD>... Чущь это...
VD>... Это тоже ахинея.

легко экстраполируется результат "дискуссии".

Так что приходится выбирать из двух зол
а эту ветку сохранить как техническое обсуждение контента данной статьи. Я выбираю второй путь, а поговорить про "рулит ленивость или нет" можно как-нибудь потом в философии — там самое место, имо.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[9]: Функциональное программирование для всех
От: Кодт Россия  
Дата: 27.10.06 09:44
Оценка: :)
Здравствуйте, VladD2, Вы писали:

VD>Если написать:

VD>def do_smth(p)
VD>{
VD>  def s("Вася", 33)
VD>  def q = 3;
VD>}

VD>то ни один супер язык не выведет типы верно. И С++ тут не причем. В этом коде банально нехватает информации.

Почему же. Хватает. Функция принимает что угодно и ничего не возвращает. Следовательно, do_smth : 'a -> unit
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[10]: Функциональное программирование для всех
От: VoidEx  
Дата: 27.10.06 10:08
Оценка:
Здравствуйте, deniok, Вы писали:

D>Ты смайлик не забыл?

D>Если нет, догадывайся, каков тип q:
D>
D>// auto предлагается в C++0x использовать для указания того, что тип выводится автоматически
D>// ниже, конечно, псевдо-С++: 
D>auto foo()
D>{
D>    auto q(7, 22.3); 
D>    return q;
D>}
D>


D>То есть ответ-то есть: тип с конструктором cons(int,double). Только что с этим обобщённым типом потом делать? Это не шаблонная (в смысле template) обобщенность.


А ФЯ в таком коде смогут вывести тип q? Явно, что тип к таким конструктором, да и дальнейшее использование этой функции можно посмотреть.
Re[10]: Функциональное программирование для всех
От: Кодт Россия  
Дата: 27.10.06 10:26
Оценка: 27 (3)
Здравствуйте, deniok, Вы писали:

У меня складывается нехорошее впечатление, что ты пытаешься развести религиозную войну на тему "ФЯ рулез ИЯ сакс".
Зачем? Какое в этом содержание?

Я уже как-то говорил, что любое обсуждение спорного вопроса может преследовать цели
— найти выход
— потренировать мозги
— выпустить пар

Не попробуем ли мы перейти к первому пункту?

Вот например, Хиндли-Милнеровская типизация.
Допустим, мы приложили некоторые усилия и сделали диалект С++ с ней.
Императивные трудности нас совершенно не волнуют. И (O)CaML, и Nemerle решили их очень просто: тип переменной выводится в точке объявления, а дальнейшие её изменения или обращения к методам только проверяются на соответствие.
Может быть, это не слишком гибко, где-то неудобно, но во всяком случае решение есть.
Итак, ХМ в С++. Как должен измениться язык? Как должен измениться компилятор?

Вот, для затравки.

Во-первых, мы теряем ad-hoc-полиморфизм — ту самую фичу, которая принесла славу С++. Что взамен? Как меняется синтаксис?
— рожаем новые операторы на все случаи жизни (подобно ML'овской целочисленной и вещественной арифметике)
— вводим typeclasses (подобно Haskell'овским) и рассовываем все полиморфные имена по ним
— учимся разделять и совмещать оба подхода: вот здесь С++ный односторонний вывод типов, а вот здесь ХМ

Во-вторых, функция с полиморфным типом — это, на самом деле, шаблон. Оставим пока за скобками работу по нахождению формальных (в точке определения) и фактических (в точках применения) параметров. Я хочу подчеркнуть, что компилятор выполняет тройную работу по кодированию:
— сперва превращает текст на входном языке во внутреннее представление (AST или какой-то промежуточный код шаблона)
— затем в точках воплощения подставляет туда фактические параметры и транслирует представление шаблона в конкретный код backend'а
— наконец, backend транслирует в целевой машинный код (в том числе выполняет оптимизации)
Чем больше конкретных функций (перегруженных или уникальных), тем меньше работы компилятору.
Сейчас тема экспорта шаблонов (т.е. сохранения промежуточного кода) задвинута. Но как только шаблоны станут халявными (сделаем-таки автоматический вывод), придётся об этом побеспокоиться.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[11]: Функциональное программирование для всех
От: Vermicious Knid  
Дата: 27.10.06 14:24
Оценка: 77 (2) +1
Здравствуйте, Кодт, Вы писали:

К>Вот например, Хиндли-Милнеровская типизация.

К>Допустим, мы приложили некоторые усилия и сделали диалект С++ с ней.
Принципиально невозможно. Систему типов C++ и типизацию Х-М никак не совместить. Классы надо сделать утино-типизированными(как в OCaml), выкинуть перегрузку, неявные приведения итд(то есть полностью забить на систему типов C++); либо забыть о Х-М. А лучше оставить C++ в покое.

К>Императивные трудности нас совершенно не волнуют. И (O)CaML, и Nemerle решили их очень просто: тип переменной выводится в точке объявления, а дальнейшие её изменения или обращения к методам только проверяются на соответствие.

Нет, в Nemerle это сделано совершенно иначе. Алгоритм Хиндли-Милнера действительно может сразу вывести тип в точке объявления, но только потому, что работает он со структурированными системами типов, где в типе выражения просто не может быть никакой неоднозначности и присутствует полная информация необходимая для немедленного вывода типа, пусть и полиморфного типа(фактически полиморфные типы выводятся направо и налево, при каждом удобном случае).

А в Nemerle есть и перегрузка функций, и неявные приведения, и прочие признаки традиционных ИЯ, которых нет в том же OCaml. Поэтому в Nemerle применяется алгоритм вывода типов, имеющий ряд серьезных принципиальных отличий от Х-М. В частности он откладывает вывод типов в неоднозначных случаях, так сказать до выяснения обстоятельств, и не выводит полиморфные типы, только конкретные(и это на мой взгляд плюс, а не минус).

Поэтому Nemerle выводит тип переменной/функции из той точки, из которой он вообще может быть выведен(т.е. произвольной ), а не из точки объявления(глобальный вывод типов правда запрещен, в том числе и по этой причине, иначе можно была бы возможность писать крайне запутанный код).

Пример вполне валидного кода на Nemerle:
using Nemerle.Collections
module Main
    foo(bar : ref int) : void
        bar++
    Main() : void
        mutable x
        // Nemerle.Collections.Hashtable это дженерик тип с двумя параметрами
        def y = Hashtable()
        // здесь мы еще не знаем ни тип x, ни точный тип y
        x = y.GetValueOrDefault("somekey")
        // вот из этой строчки и будет выведен тип x
        foo(ref x)
        // напечатает 1
        System.Console.WriteLine(x)

Еще один пример, на этот раз разруливание перегрузки:
module Main
    foo(_ : int) : void { }
    foo(_ : float) : void { }
    bar() : int { 1 }
    Main() : void
        // какой именно foo нам нужен?
        def f = foo
        // вот здесь компилятор это выяснит
        f(bar())
        // более сложный случай
        def foobar = (f,b) => f(b())
        foobar(foo,bar)

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

К>Во-первых, мы теряем ad-hoc-полиморфизм — ту самую фичу, которая принесла славу С++. Что взамен? Как меняется синтаксис?

Совсем не обязательно. В Nemerle фактически есть ad-hoc полиморфизм, с помощью макросов. Теоретически, мне кажется, нет никаких препятствий для добавления в Nemerle шаблонов a-la C++, кроме того конечно, что в этом крайне мало смысла.
Re[10]: Функциональное программирование для всех
От: deniok Россия  
Дата: 27.10.06 14:29
Оценка: :)
Здравствуйте, deniok, Вы писали:

Спасибо всем (отдельно Кодту за обычную содержательность). Был неправ. Хотел поставить себе минус, но не обнаружил такой возможности.

Разаработчикам: поддержите возможность самокритики
Re[10]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 17:11
Оценка:
Здравствуйте, Кодт, Вы писали:

VD>>Если написать:

К>
VD>>def do_smth(p)
VD>>{
VD>>  def s("Вася", 33)
VD>>  def q = 3;
VD>>}
К>

VD>>то ни один супер язык не выведет типы верно. И С++ тут не причем. В этом коде банально нехватает информации.

К>Почему же. Хватает. Функция принимает что угодно и ничего не возвращает. Следовательно, do_smth : 'a -> unit


А, ну, если только так. Тогда переменные можно описать как "любая хрень" и сделать вывод, что для программ ничего неделающих и оперирующих хрен знает чем можно делать вывад типов без каких либо проблем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 17:18
Оценка:
Здравствуйте, Кодт, Вы писали:

К>К императивности отношения не имеет вообще. Хотя бы потому, что этот подход распространяется и на язык шаблонов (чисто декларативный), в котором вообще царит утиная типизация.


Кстати, Хиндли-Милер по крайней мере из ОКамла — это тоже утиная типизация.

К>printf не в виде макроса, а в виде функции. Замучаетесь и обломитесь!)


Надо признать что printf как раз замечательная задача именно для продвинутых макросов. А универсальными средствами языка printf получается очень плохо (как в С, например).

К>В Лиспе типизация утиная, а ведь тоже ФЯ...


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

ЗЫ

Вообще, количество алогизмов и отновенного обамана в области популяризации ФП просто поражает. Меня вот интересут вопрос. Это такое количество безвинных заблудших овечек или это генеральная линия партии проталкивать ФП любыми (в том числе не корректными) средствами? Уж больно странно видеть такие детские логические ошибки от такого количества народу претендующего на звание гуру.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 17:46
Оценка: -2
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>О, да, известный Борец-С-Ветряными-Мельницами.


Скорее с демагогами и болоболами.

LCR>В чём смысл борьбы то?


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

LCR>Борьба с неверными () али движение за мировое господство "ТхеРигхтТхинга" ()?


С безграмотными алогизмами и отровенной ложью.

LCR>В принципе я бы мог потратить время и ответить подробно, с примерами и пояснениями


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

Собственно не ясно в чем дело. Ну, нравится тебе или еще кому-то тот или иной подход. Та или иноая парадигма. Ну, так замечательно! Обясняйте принципы людям. Говоритие о приемуществах, недостатках, проблемах, задачах, решениях... Но не нужно в очередной раз разводит отровенную демогогию в стиле "Россия родина слонов".

Используйте принцип — логика пре выше всего. И все будет ОК. Не надо делать столь очевидно ошибочных утверждений. Не надо связвать с функциональной парадигмой все что появилось или развилось в функциональных языка. Ведь так же просто. Если мы считаем ML функциональным языком, а в нем нет линивости, и есть возожность менять переменные, то разговор о том что то и другое являются неотемлиыми частами ФЯ надо закрыть. Это просто свойства конкретного языка. Не больше и не менее.

LCR> (btw, строгого доказательства в принципе сделать невозможно, поскольку речь идёт о человеке и вопрос "легче/труднее" часто субъективен и неформален), почему с ростом сложности систем сложность реализации ленивых вычислений в условиях mutable state растёт экспоненциально, но увы, после таких доводов


Не идет речь о человеке. Речь идет об утверждениях и о том, что они легко опровергаются. Вы смело смотрите на четкие опровержения этих суждений, но вместо того чтобы согласиться с тем что суждения эти не верны, вы не менее смело продолжатее делать вид, что все ОК и продлжатее дальше повторять заученные мантры из религиозной пропаганды.

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

LCR>

VD>>... Чущь это...
VD>>... Это тоже ахинея.

LCR>легко экстраполируется результат "дискуссии".

Нет никакой дисскусси. И именно эти слова очень точно и четко определяют суть происходящего. Есть религизная ахинея и чушь которую под разным соусом пытются навязать окружающим.

LCR>Так что приходится выбирать из двух зол

LCR> LCR>а эту ветку сохранить как техническое обсуждение контента данной статьи.
LCR>

Невижу связи. RSDN несомненно не единственный. Но лично я, не запреща другим выражать свое мнение, буду выражать свое мнение. И если оно не совпадает с чьим-то то это его проблемы. Ради уважения к окружающим или политкоректности я не буду называть черное белым или делать вид что ничего не слышу или со всем согласен.

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

LCR>Я выбираю второй путь, а поговорить про "рулит ленивость или нет" можно как-нибудь потом в философии — там самое место, имо.


Я даже не хочу обсуждать рулит ленивость или нет. Я утверждаю, что линивость не имеет прямой связи с ФЯ. Это качество конкретного зяка. И зачем к банльному логическому выводу прицеплять положение RSDN в рунете или разумность читателя я не знаю. Кстати, судя по тому, что религиозный булшит поражает кучу неокрепших мозгов я сильно сомневаюсь, что утверждение "читатель разумен и фильтрует любые сообщения" всегда и не для всех верно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 17:54
Оценка: 26 (1)
Здравствуйте, Кодт, Вы писали:

К>Императивные трудности нас совершенно не волнуют. И (O)CaML, и Nemerle решили их очень просто: тип переменной выводится в точке объявления, а дальнейшие её изменения или обращения к методам только проверяются на соответствие.


Как минимум для Nemerle это не верно. Этот язык выводит тип перменных и функций из ближайшего использования. Причем иногда может вывести базовый тип (хотя там есть ограничения связанные с тем что ситуция в кторой выведен очень общий тип чаща бывает ошибкой). Так что точнее будет сказать "тип выводится из использования и/или объявления". Классический пример:
def h = Hashtable();
h.Add("aaa", 1);
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 18:05
Оценка: +1
Здравствуйте, Vermicious Knid, Вы писали:

VK>Совсем не обязательно. В Nemerle фактически есть ad-hoc полиморфизм, с помощью макросов.


Насколько я понимаю терминт ad-hoc-полиморфизм означет банальную перегрузку. Так что Nemerle полностью и без проблем поддерживает ad-hoc-полиморфизм. Причем делает это напрямую.

Просто шаблоны С++ изобилуют пергрузкой. Но в их случае скорее нужно говорить об утиной типизации которой действительно в Nemerle можно добиться только если использовать шаблоны или методы-расширения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Функциональное программирование для всех
От: Vermicious Knid  
Дата: 27.10.06 18:40
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Насколько я понимаю терминт ad-hoc-полиморфизм означет банальную перегрузку. Так что Nemerle полностью и без проблем поддерживает ad-hoc-полиморфизм. Причем делает это напрямую.

Ну это был бы не я, если бы в чем-нибудь не ошибся. Жаль уже сообщение исправить нельзя. А ведь главное что когда-то видел определение этого термина, просто в памяти не отложилось.

VD>Просто шаблоны С++ изобилуют пергрузкой.

Да, мне кажется шаблоны, их специализация, и перегрузка в C++ действительно очень тесно связаны. И я думаю, что Немерловский вывод типов вполне совместим с системой типов вроде системы типов C++(ну может разве что чуть-чуть упростить ее нужно). Собственно примерно в этом исходная мысль и заключалась.

Правда язык с шаблонами C++ и выводом типов Nemerle это было бы нечто монстрообразное. А если туда еще и макросы.
Re[9]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 27.10.06 21:28
Оценка: -1
Здравствуйте, VladD2, Вы писали:

VD>Используйте принцип — логика пре выше всего. И все будет ОК. Не надо делать столь очевидно ошибочных утверждений. Не надо связвать с функциональной парадигмой все что появилось или развилось в функциональных языка. Ведь так же просто. Если мы считаем ML функциональным языком, а в нем нет линивости, и есть возожность менять переменные, то разговор о том что то и другое являются неотемлиыми частами ФЯ надо закрыть. Это просто свойства конкретного языка. Не больше и не менее.


Какое свойство ФП не назови — оно или будет в каком то ИЯ, или его не будет в каком то ФЯ.
Вот тогда по твоему, что такое ФП? Каковы его отличительные особенности? И что такое ФЯ?
Re[10]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.10.06 21:41
Оценка: :)
Здравствуйте, lomeo, Вы писали:

L>Какое свойство ФП не назови — оно или будет в каком то ИЯ, или его не будет в каком то ФЯ.

L>Вот тогда по твоему, что такое ФП? Каковы его отличительные особенности? И что такое ФЯ?

Есть одно четкое свойство выделяющее ФЯ — запись программы в виде выражений (expressions), а не statements.

Так же все ФЯ отличаются расширенной поддержкой функций высшего порядка: замыканий, локальных и/или анонимных функций.

Но чето практически правада — это что все кроме того что функция в таких языках является первоклассным значением и то что функции строются из выражений не является частным достоянем функциональных языков.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 28.10.06 13:54
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Есть одно четкое свойство выделяющее ФЯ — запись программы в виде выражений (expressions), а не statements.


Т.е. программа — это одна большая функция.

VD>Так же все ФЯ отличаются расширенной поддержкой функций высшего порядка: замыканий, локальных и/или анонимных функций.


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


Честно говоря, частным достоянием и это не является.

Я что сказать хочу. Чистота функций (отсутствие сайд эффекта), ФВП, рекурсия — это особенности ФП. Они есть и в ИЯ и в ФЯ (деление на ИЯ и ФЯ ведь достаточно условно, все это понимают?) От того, что они есть в ИЯ не делает их не ФП-шными фичами. Это я к твоей фразе о том, что "ФП — это отсутствие побочных эффетов — ахинея". ФП, конечно, это не отсутсвие сайд эффектов, но отсутствие сайд эффектов — отличительная черта ФП. И то, что можно без сайд эффектов писать на ИЯ, и то, что есть ФЯ с сайд эффектами — ни о чем не говорит. ФЯ — всего лишь язык, облегчающий программирование в ФП-стиле.

Про ленивость, полагаю, не так. Это черта конкретных языков (но! нефункиональные языки не знаю). Имеется в виду по дефолту, разумеется, т.е. поддержка языком non-strict evaluation.
Re[12]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.10.06 14:47
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Т.е. программа — это одна большая функция.


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

L>Честно говоря, частным достоянием и это не является.


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

L>Я что сказать хочу. Чистота функций (отсутствие сайд эффекта), ФВП, рекурсия — это особенности ФП.


Особености?

L>Они есть и в ИЯ и в ФЯ (деление на ИЯ и ФЯ ведь достаточно условно, все это понимают?)


Все? Да, постоянно ленивость объясляется чуть ли не основпологающей особенностью ФЯ. И этот бред несется на фоне прославления того же Эрлэнга в соседних ветках. Так что отнюдь не все. Большинство людей начитались религиозных агиток и несут форменную ахинею.

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

К сожалению, многие ставят знак равенства между этими утвердениями, что превращает попытки классификации те же языков в форменную вакханалию.

L>От того, что они есть в ИЯ не делает их не ФП-шными фичами.


Делает, делае. Правда в том, что ФП — это стиль программирования. А ФЯ — это языки заточенные на этот стиль в большей степени. Так называемые чистые ФЯ есть ни что иное как сильно ограниченные ЯП в которых можно программировать исклчительно в о функциональном стиле.

Определяющим же свойством ФЯ является исключительно то что программа строится как выражение. А уже все остальное в плодь до побочных эффектов является следствием этого.

Но вот такие вещи как паттерн-матчинг или ленивость никак не связанные с этой особенностью и являются исклюичтельно выбором дизайнеров языка.

L>Это я к твоей фразе о том, что "ФП — это отсутствие побочных эффетов — ахинея". ФП, конечно, это не отсутсвие сайд эффектов, но отсутствие сайд эффектов — отличительная черта ФП.


Конечно же отличительной чертой это не является, так как большая часть ФЯ позволяют менять переменные, и немало ИЯ имеют синтаксис для создания неизменяемых переменных. Если сказать, что это отилчительная черта, то С++ — это ФЯ.

Скажем так — любой ФЯ (в отличии от ИЯ) имеет синтаксис для создания неизменяемых переменных и обеспечивает возможность программировать вообще не используя изменяемые переменные.

L>И то, что можно без сайд эффектов писать на ИЯ, и то, что есть ФЯ с сайд эффектами — ни о чем не говорит.


Это говорит о том, что твое утверждение неверно. Более не о чем.

L>ФЯ — всего лишь язык, облегчающий программирование в ФП-стиле.


Именно. Но это определение почему-то сильно не устраивает многих любителей ФП.

L>Про ленивость, полагаю, не так.


Линивость вообще приплетена по недоразумению. Собственно это и есть та логическая ошибка о которой я говорил. Ни ФЯ, ни ИЯ не обязаны иметь линивую семантику вообще, и не обязаны ее пддерживать. В прочем ни что не мешает ее поддерживать любому языку. Правдой является только одно утверждение — В чистых ФЯ проще реализовать ленивую семантику, так как вообще не надо думать о побочных эффектах.

L>Это черта конкретных языков (но! нефункиональные языки не знаю). Имеется в виду по дефолту, разумеется, т.е. поддержка языком non-strict evaluation.


Читайте Красного дракона Аха. Там как раз разбираются принципы предачи параметров в процедуры и как один из них разбирается способ передачи аналогичный тому что называется ленивым в облати ФЯ. Причем там же говорится о языках где это встречалось в первые и то том, что это было не очень хорошо именно потому, что в следствии побочных эффектов приводило к сложности понимания происходящего.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Функциональное программирование для всех
От: VoidEx  
Дата: 28.10.06 19:33
Оценка:
Здравствуйте, VladD2, Вы писали:

L>>Это я к твоей фразе о том, что "ФП — это отсутствие побочных эффетов — ахинея". ФП, конечно, это не отсутсвие сайд эффектов, но отсутствие сайд эффектов — отличительная черта ФП.


VD>Конечно же отличительной чертой это не является, так как большая часть ФЯ позволяют менять переменные, и немало ИЯ имеют синтаксис для создания неизменяемых переменных. Если сказать, что это отилчительная черта, то С++ — это ФЯ.


Вот тут Вы сами логику нарушаете. В Си++ нет отсутствия побочных эффектов. Без них можно писать, но отсутствия там нет.
Хотя Ваш оппонент тоже логику нарушает так как если это отличительная черта, то она должна быть свойственна всем ФЯ.

Можно сказать так, отличительной чертой ФЯ является то, что некоторые из них имеют отсутствие побочных эффектов. Тогда будет верно (если, конечно, нет таких ИЯ, которые не позволяют писать с побочными эффектами).

П.С. Под отсутствием побочных эффектов, само собой, подразумевается не тотальное их отстутствие (иначе на таком языке и программу-то не напишешь), а такое, как например в Хаскеле.
Re[14]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 28.10.06 23:59
Оценка: 1 (1)
Здравствуйте, VoidEx, Вы писали:

VE>Хотя Ваш оппонент тоже логику нарушает так как если это отличительная черта, то она должна быть свойственна всем ФЯ.


VE>Можно сказать так, отличительной чертой ФЯ является то, что некоторые из них имеют отсутствие побочных эффектов. Тогда будет верно (если, конечно, нет таких ИЯ, которые не позволяют писать с побочными эффектами).


Я говорил, что это отличительная черта ФП, а не ФЯ. Программировать в функиональном стиле — это значит писать код с ФВП и чистыми функциями. Примерно так. Влад вот тоже часто путает ФЯ и ФП.

Ну и во вторых, фраза о том, что в С++ нет отсутствия побочных эффектов, к сожалению, имеет мало смысла (в контексте разговора, конечно!). Главное, что на С++ можно написать программу без сайд эффектов.
Re[13]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 28.10.06 23:01
Оценка: +1
Здравствуйте, VladD2, Вы писали:

L>>Я что сказать хочу. Чистота функций (отсутствие сайд эффекта), ФВП, рекурсия — это особенности ФП.


VD>Особености?


Э-э-э, да... Что смущает?

L>>От того, что они есть в ИЯ не делает их не ФП-шными фичами.


VD>Делает, делае.


ФВП — не ФП фича? Не думаю, что могу согласится с этим. Это же два способа делать одно и то же — состояния в ИЯ и ФВП в ФП.
Использование ФВП, кстати, вытекает из того, что программа есть выражение, а не набор стейтментов.

L>>Это я к твоей фразе о том, что "ФП — это отсутствие побочных эффетов — ахинея". ФП, конечно, это не отсутсвие сайд эффектов, но отсутствие сайд эффектов — отличительная черта ФП.


VD>Конечно же отличительной чертой это не является, так как большая часть ФЯ позволяют менять переменные, и немало ИЯ имеют синтаксис для создания неизменяемых переменных. Если сказать, что это отилчительная черта, то С++ — это ФЯ.


ФЯ — это язык, "облегчающий писать в ФП стиле", а не "позволяющий писать в ФП стиле".

VD>Скажем так — любой ФЯ (в отличии от ИЯ) имеет синтаксис для создания неизменяемых переменных и обеспечивает возможность программировать вообще не используя изменяемые переменные.


На С++ всё это, как ты уже заметил, тоже есть. Про "обеспечивает возможность", правда, не уверен, потому что не понимаю, что это значит. Но позволяет, да.

L>>И то, что можно без сайд эффектов писать на ИЯ, и то, что есть ФЯ с сайд эффектами — ни о чем не говорит.


VD>Это говорит о том, что твое утверждение неверно. Более не о чем.


Ты вот постоянно аппелируешь к логике, но сам ей пользуешься нечасто. Берем твое утверждение о том, что ФП — это когда программа записана в виде выражений. Записываем так на С++. Опа! С++ — ФЯ! Так что ли?

VD>Читайте Красного дракона Аха.


Читали
Re[10]: Функциональное программирование для всех
От: Андрей Хропов Россия  
Дата: 29.10.06 23:39
Оценка: +1
Здравствуйте, Кодт, Вы писали:

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


VD>>Если написать:

К>
VD>>def do_smth(p)
VD>>{
VD>>  def s("Вася", 33)
VD>>  def q = 3;
VD>>}
К>

VD>>то ни один супер язык не выведет типы верно. И С++ тут не причем. В этом коде банально нехватает информации.

К>Почему же. Хватает. Функция принимает что угодно и ничего не возвращает. Следовательно, do_smth : 'a -> unit


Да, и если язык чисто функциональный (без побочных эффектов), то т.к. дальше s не используется и побочных эффектов
от ее инициализации нет, то ее можно просто выкинуть, неважно могла ли она иметь какой-то тип или нет .
Как впрочем и q.
Так что информации хватило .

Да, получается в чисто функциональном языке ничего не возвращающие функции не имеют смысла.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[14]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.10.06 02:54
Оценка:
Здравствуйте, VoidEx, Вы писали:

VD>>Конечно же отличительной чертой это не является, так как большая часть ФЯ позволяют менять переменные, и немало ИЯ имеют синтаксис для создания неизменяемых переменных. Если сказать, что это отилчительная черта, то С++ — это ФЯ.


VE>Вот тут Вы сами логику нарушаете. В Си++ нет отсутствия побочных эффектов. Без них можно писать, но отсутствия там нет.


Я логику не нарушаю. Это делает явно кто-то другой. Я не утверждал что С++ непозволяте делать побочных эффектов. Я утверждал, что как и любой ФЯ он позволяет писать код без побочных эффектов.

VE>Хотя Ваш оппонент тоже логику нарушает так как если это отличительная черта, то она должна быть свойственна всем ФЯ.


Именно.

VE>Можно сказать так, отличительной чертой ФЯ является то, что некоторые из них имеют отсутствие побочных эффектов.


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

VE>Тогда будет верно (если, конечно, нет таких ИЯ, которые не позволяют писать с побочными эффектами).


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

Так что разумно говорить, что ФП — это программирование в выражениях которое стимулирует программирование без побочных эффектов. Причем именно ФП, а не ФЯ! ФЯ же не более чем класс языков полноценно (и с достаточным удобством) поддерживающих программирование в выражениях.

VE>П.С. Под отсутствием побочных эффектов, само собой, подразумевается не тотальное их отстутствие (иначе на таком языке и программу-то не напишешь), а такое, как например в Хаскеле.


По-моему — это все пуританство. Разумно было бы ввести в язык некую аннотацию функций гарантирующую отсуствие в них побочных эффетов. Но заниматься такой ахинейй как монады в Хаскеле — это явно чересчур.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.10.06 02:56
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Я говорил, что это отличительная черта ФП, а не ФЯ. Программировать в функиональном стиле — это значит писать код с ФВП и чистыми функциями. Примерно так. Влад вот тоже часто путает ФЯ и ФП.


Примеры такой путанницы, плиз, приведи.

L>Ну и во вторых, фраза о том, что в С++ нет отсутствия побочных эффектов, к сожалению, имеет мало смысла (в контексте разговора, конечно!). Главное, что на С++ можно написать программу без сайд эффектов.


Кстати, фраза "что в С++ нет отсутствия побочных эффектов" это банальное перевирание моих слов. Я такого не говорил.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.10.06 03:25
Оценка:
Здравствуйте, lomeo, Вы писали:

L>>>Я что сказать хочу. Чистота функций (отсутствие сайд эффекта), ФВП, рекурсия — это особенности ФП.


VD>>Особености?


L>Э-э-э, да... Что смущает?


1. Неопределнность термина.
2. Как особенностью стиля программирования может выступать использование фич конкретного языка?

Ееще раз повторюсь. Главной отличительной чертой ФП и соотвествнно ФЯ является программирование в выржениях. А уж все остальное от побочных эффетов, до постоянного применения ФВП — это следствия использоания стиля.

L>>>От того, что они есть в ИЯ не делает их не ФП-шными фичами.


VD>>Делает, делае.


L>ФВП — не ФП фича?


Нет конечно. Она же с успехом применяется в императивном коде. Примеры колбэков имзеняющих переменные и т.п. тому свидетельство.

L>Не думаю, что могу согласится с этим. Это же два способа делать одно и то же — состояния в ИЯ и ФВП в ФП.


Какая тут связь? Вот тебе приколнейший код:
using System.Console;

mutable var = 0;

def getCerrentState() { var }
def setCerrentState(newVal) { var = newVal }
def printIt(f) { WriteLine(f()); }

printIt(getCerrentState);
setCerrentState(getCerrentState() + 1);
printIt(getCerrentState);

Он выводит на консоль:
0
1

Он использует замыкания и ФВП. Причем делает это "во все дыры", что называется. Он он императивен по сути, так как использует побочные эффекты. А это явное противоречие если исходить из ваших позиций.

L>Использование ФВП, кстати, вытекает из того, что программа есть выражение, а не набор стейтментов.


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

И использованием ФВП ничего само по себе не говорит. Конечно любое варажение в крограмме можно рассматривать как использования функционального стиля программирования. Но насколько разумен такой взгляд?

L>ФЯ — это язык, "облегчающий писать в ФП стиле", а не "позволяющий писать в ФП стиле".


С этим можно согласиться. Я бы даже сказал "имеющий достаточный набор средств для программирования в ФС".

VD>>Скажем так — любой ФЯ (в отличии от ИЯ) имеет синтаксис для создания неизменяемых переменных и обеспечивает возможность программировать вообще не используя изменяемые переменные.


L>На С++ всё это, как ты уже заметил, тоже есть.


А я что спорю? А в С и C# нет. Ну, и что?

L>Ты вот постоянно аппелируешь к логике, но сам ей пользуешься нечасто. Берем твое утверждение о том, что ФП — это когда программа записана в виде выражений. Записываем так на С++. Опа! С++ — ФЯ! Так что ли?


А зачем ты все время смешиваешь понятия ФЯ и ФП. Жонглирование ими и приводит к путаннице.

Исходно я был против утверждения "ленивость и отсуствие побочных эффектов есть отличительные особености ФЯ".

В С++ несомненно есть ФВП, рекурсия и выражения. Этого более чем достаточно для того чтобы писать на С++ в ФС. Но С++ не ФЯ. И единственное что его по большому счету отличает от ОКамла в этом плане — это неудобность программирования в выражениях. Большинство его конструкций являются стэйтментами. Программируя на С++ в ФС ты вунужден будешь ограничиться оперотором ?:, вызовом функций и пожалй что теми самыми ФВП. А этого явно мало для полноценного программирования.

VD>>Читайте Красного дракона Аха.

L>Читали

Тогда должне был обратить внимание н раздел посвященный передаче аргументов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Функциональное программирование для всех
От: Mirrorer  
Дата: 30.10.06 08:03
Оценка:
Здравствуйте, Кодт, Вы писали:

К>- вводим typeclasses (подобно Haskell'овским) и рассовываем все полиморфные имена по ним


А вот подумалось что-то..

В C# 2.0 появилась возможность писать

interface ISomeInterface<T>
{
    void DoSmth(T val);
}


Можно ли это считать аналогом typeclasses, или я упускаю какую-то существенно важную вещь ?

В качестве продолжения извращений..

Допустим вот монада
    // (a -> m b) 
    public delegate IMonad<B> BindDelegate<A,B>(A a);
    
    public interface IMonad<A>
    {
        // return :: a -> m a
        IMonad<A> ret(A val);
        // bind, >>= :: m a -> (a -> m b) -> m b
        IMonad<B> bind<B>(IMonad<A> ma,BindDelegate<A,B> binder);
    }

А вот это Maybe
    public  class  Maybe<A> : IMonad<A>
    {
        #region IMonad<A> Members

        public IMonad<A> ret(A val)
        {
            return new Just<A>(val);
        }

        public IMonad<B> bind<B>(IMonad<A> ma, BindDelegate<A,B> binder)
        {
            if (ma is Just<A>)
                return binder((A)(ma as Just<A>).Val);

            return new Nothing<B>();
        }

        #endregion
    }
    public class Nothing<A> : Maybe<A>
    {
        public Nothing()
        { 
        
        }
    }
    public class Just<A> : Maybe<A>
    {
        public readonly object Val;
        public Just(A val)
        {
            Val = val;
        }
    }


По аналогии с
firstElement :: [a] -> Maybe a
firstElement [] = Nothing
firstElement (x:xs) = Just x


Метод возвращающий Maybe

        static Maybe<A> firstElement<A>(List<A> list)
        {
            if (list.Count == 0)
                return new Nothing<A>();
            return new Just<A>(list[0]);
        }


ну и соответственно использование

    List<int> empty = new List<int>();
    // выведет SharpMonads.Nothing`1[System.Int32]
    
    Console.WriteLine(firstElement<int>(empty).ToString());
    empty.Add(42);
    
    // выведет SharpMonads.Just`1[System.Int32]
    Console.WriteLine(firstElement<int>(empty).ToString());


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

З.Ы. выполнение монадических законов не проверял
... << RSDN@Home 1.1.4 Adriano Celentano — Dimenticare e ricominciare >>
Re[15]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 30.10.06 08:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>1. Неопределнность термина.

VD>2. Как особенностью стиля программирования может выступать использование фич конкретного языка?

VD>Ееще раз повторюсь. Главной отличительной чертой ФП и соотвествнно ФЯ является программирование в выржениях. А уж все остальное от побочных эффетов, до постоянного применения ФВП — это следствия использоания стиля.


Опять спор будет о терминах, что такое следствие, да что такое фича. Не хочу.

L>>ФВП — не ФП фича?


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


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

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

Так что, на мой взгляд, ФВП — это фича ФП.

Остальное вертится вокруг этого, поэтому поскипаю.
Re[16]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 30.10.06 09:06
Оценка:
Здравствуйте, VladD2, Вы писали:

L>>Влад вот тоже часто путает ФЯ и ФП.


VD>Примеры такой путанницы, плиз, приведи.


Ой, Влад, да это происходит практически постоянно. Вот из последнего только:

Так что разумно говорить, что ФП — это программирование в выражениях которое стимулирует программирование без побочных эффектов. Причем именно ФП, а не ФЯ!

Хотя до этого ты говорил,

Есть одно четкое свойство выделяющее ФЯ — запись программы в виде выражений (expressions), а не statements.

А вот ещё:

L>Это я к твоей фразе о том, что "ФП — это отсутствие побочных эффетов — ахинея". ФП, конечно, это не отсутсвие сайд эффектов, но отсутствие сайд эффектов — отличительная черта ФП.

Конечно же отличительной чертой это не является, так как большая часть ФЯ позволяют менять переменные, и немало ИЯ имеют синтаксис для создания неизменяемых переменных. Если сказать, что это отилчительная черта, то С++ — это ФЯ.


Хотя, как мне показалось, ты понимаешь условность названия ФЯ.

Если же поднять наш тред из ООП vs ФП, то там это происходит постоянно. Просто лень копаться.
Re[17]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.10.06 09:26
Оценка:
Здравствуйте, lomeo, Вы писали:

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


L>Ой, Влад, да это происходит практически постоянно. Вот из последнего только:

L>

Так что разумно говорить, что ФП — это программирование в выражениях которое стимулирует программирование без побочных эффектов. Причем именно ФП, а не ФЯ!

L>Хотя до этого ты говорил,
L>

Есть одно четкое свойство выделяющее ФЯ — запись программы в виде выражений (expressions), а не statements.


И в чем тут путанница?

L>А вот ещё:

L>

L>>Это я к твоей фразе о том, что "ФП — это отсутствие побочных эффетов — ахинея". ФП, конечно, это не отсутсвие сайд эффектов, но отсутствие сайд эффектов — отличительная черта ФП.

L>Конечно же отличительной чертой это не является, так как большая часть ФЯ позволяют менять переменные, и немало ИЯ имеют синтаксис для создания неизменяемых переменных. Если сказать, что это отилчительная черта, то С++ — это ФЯ.


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

L>Хотя, как мне показалось, ты понимаешь условность названия ФЯ.


Мне тоже так кажется. Я даже почти уверен.

L>Если же поднять наш тред из ООП vs ФП, то там это происходит постоянно. Просто лень копаться.


А. Ну, ну.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: Функциональное программирование для всех
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 30.10.06 09:45
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Насколько я помню ты влез по середине разговра в котором говрилось приемущественно о ФЯ.


Ой, извини, и в сабже об этом же, как же это я?
Re[3]: Функциональное программирование для всех
От: minorlogic Украина  
Дата: 04.11.06 09:14
Оценка: :)
Я не вижу как какому либо описаному методу поможет сборка мусора.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[3]: Функциональное программирование для всех
От: minorlogic Украина  
Дата: 04.11.06 09:20
Оценка:
Т.е. вы подтверждаете в общем мою мысль, что ФЯ и приемы описанные в статье только делают удобными некоторые ОБЩЕПРИНЯТЫЕ приемы программирования которые в других языках возможны но используются не так широко.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[3]: Функциональное программирование для всех
От: minorlogic Украина  
Дата: 04.11.06 09:21
Оценка: :)
Здравствуйте, VladD2, Вы писали:

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


M>>Это моя беглая точка зрения , после первого прочтения. Комментированные минусы за мою ткпость велкам !


VD>По просбам трудящийся поставил минус.


VD>И что немало важно от души.


VD>Аргументирую так. Ты не знаешь о чем говоришь. Поробуй, а потом еще раз выскажись. Уверен, что твое мнение сильно изменится.


Я ожидал ответ на свой пост комментарий по существу , а не бред обиженного ребенка. Но Влад от тебя что еще можно ожидать ?



VD>ЗЫ


VD>Думаю самую плохую услугу ФП оказывают его популяризаторы. Они перегибают палку часто доводя рекламу ФП до уровня рекламы гебалайфа.


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





VD>Продолжения это вообще мега-фича только вот к ФП в общем-то не относящаяся. В прочем ФП вообще илюзорен. Это набор паттернов кторый можно без проблем применять в ИЯ. Основное достоинство ФЯ заключается в том, что они резко упрощают использование этого стиля.


Именно это я и сказал в предыдущем посте, ты его вообще прочел, или как всегда ... ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[4]: Функциональное программирование для всех
От: FR  
Дата: 04.11.06 09:37
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Т.е. вы подтверждаете в общем мою мысль, что ФЯ и приемы описанные в статье только делают удобными некоторые ОБЩЕПРИНЯТЫЕ приемы программирования которые в других языках возможны но используются не так широко.


Скорее вообще не используются по незнанию или неудобству.
Кроме того это самое удобство дает куммулятивный эффект, начинаешь не только писать (в смысле кодирования, или конструрования по Макконелу) но и делать декомпозицию и проектирование по другому.
Re[15]: Функциональное программирование для всех
От: Андрей Хропов Россия  
Дата: 05.11.06 22:31
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Нет. С точки зрения чистого ФП — программа это функция y = f(x). Дал ей x, она выдала y.
Вот этот y и есть ее результат для внешнего мира.

VD>По-моему — это все пуританство. Разумно было бы ввести в язык некую аннотацию функций гарантирующую отсуствие в них побочных эффетов.

Что и сделано в C++
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[16]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.11.06 10:42
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Нет. С точки зрения чистого ФП — программа это функция y = f(x). Дал ей x, она выдала y.

АХ>Вот этот y и есть ее результат для внешнего мира.

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

VD>>По-моему — это все пуританство. Разумно было бы ввести в язык некую аннотацию функций гарантирующую отсуствие в них побочных эффетов.

АХ>Что и сделано в C++

Отнюдь. В С++ вообще ничего не гарантируется по причине наличия указателей и ассемблерных вставок.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Функциональное программирование для всех
От: Андрей Хропов Россия  
Дата: 06.11.06 12:37
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Андрей Хропов, Вы писали:


АХ>>Нет. С точки зрения чистого ФП — программа это функция y = f(x). Дал ей x, она выдала y.

АХ>>Вот этот y и есть ее результат для внешнего мира.

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


Ну хорошо, давай калькулятор.

Что такое пользователь? Это на самом деле функция AskUser( results ) которой даешь результаты, а она возвращает то что он ввел.

Вот как он приблизительно работает (императивно)

Results Calculator( )
{
    Results results = null;

    while( true )
    {
        Input input = AskUser( results );
        if( input == null )
            break;
        else    
            results = DoMath( input, results ); // или DoMath(input) если программа не использует предыдущие вычисления
    }
    
    return results;
}


Теперь перепишем это же в функциональном стиле на Nemerle

Calculator() : Results
{
    def AskFunc(results)
    {
        ( AskUser( results ), results )
    }

    def Calc(input,results)
    {
        if(input == null)
            results
        else
            Calc( AskFunc( DoMath( input, results ) ) )    // или DoMath(input) если программа не использует предыдущие вычисления
    }

    Calc( AskFunc(null) )
}


P.S. При попытке проверить на практике компилятор Nemerle выдал ice . Будем разбираться.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[18]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.11.06 13:23
Оценка: -3 :)
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Ну хорошо, давай калькулятор.


АХ>Что такое пользователь? Это на самом деле функция AskUser( results ) которой даешь результаты, а она возвращает то что он ввел.


Любой вывод информации пользователю — это побочный эффект. Точка!

Фунициональное программирование — это аксиморон. Оно невозможно в принципе.

Можно писать 99.9% кода в фукнциональном стиле, но программы не будет если не будет побочных эффектов. Так что вопрос только в их количестве и в том, что они дают.

Отсюда и все внеполовые изврещения вроде монад в Хаскеле. Все это попытка спрятать банальную правду императивности компьютера за розовыми очками математических абстракций.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: Функциональное программирование для всех
От: VoidEx  
Дата: 06.11.06 13:36
Оценка: +1
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Что такое пользователь? Это на самом деле функция AskUser( results ) которой даешь результаты, а она возвращает то что он ввел.


Стоп стоп! А эта функция чистая? Пользователь при одинаковых параметрах будет под угрозой удара током что ли вводить одинаковые значения?
Re[19]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 06.11.06 14:13
Оценка: +1 -1 :)
VoidEx,

АХ>>Что такое пользователь? Это на самом деле функция AskUser( results ) которой даешь результаты, а она возвращает то что он ввел.


VE>Стоп стоп! А эта функция чистая? Пользователь при одинаковых параметрах будет под угрозой удара током что ли вводить одинаковые значения?


Конечно чистая.
user(Timestamp) -> ...

И вообще, _весь_ ввод-вывод можно представить в виде функции
NewWorld = io_fun(OldWorld).

Единственым препятствием для была трудность практической реализации такого подхода. Однако прогресс на месте не стоит, и создатели Clean сделали это, причём весьма эффективно.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[19]: Функциональное программирование для всех
От: Андрей Хропов Россия  
Дата: 06.11.06 14:37
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, Андрей Хропов, Вы писали:


АХ>>Что такое пользователь? Это на самом деле функция AskUser( results ) которой даешь результаты, а она возвращает то что он ввел.


VE>Стоп стоп! А эта функция чистая? Пользователь при одинаковых параметрах будет под угрозой удара током что ли вводить одинаковые значения?


Хорошо, уточню. Если мы считаем, что пользователь мыслит рационально и его дальнейшие действия основываются только на результатах — то да. Если не только на результатах но и на исходных мыслях, то тогда скажем, заменим results на (results,user_thoughts) и в начале будем передавать не null,
а (null,some_thoughts).

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

Но вообще говоря со случайными функциями тоже можно работать.
Только результат тоже будет случайной функцией.

Даже такие языки программирования есть (например Java2K ).
А для квантовых языков программирования это вообще естественная ситуация, т.к. кубиты, которыми они манипулируют вообще говоря — случайные величины.

Но с другой стороны, если почитать в Wikipedia про Pure Functional

Purely functional is a term in computing used to describe algorithms, data structures or programming languages that exclude destructive modifications (updates).


и

side effects

In computer science, a function is said to produce a side effect if it modifies some state other than its return value.


Как видишь про детерминированность ничего не говорится.
А как на практике скажем в Haskell, работают с недетерминированными функциями было бы интересно услышать от его знатоков
(я не являюсь таковым к сожалению).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[20]: Функциональное программирование для всех
От: VoidEx  
Дата: 06.11.06 15:52
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Единственым препятствием для была трудность практической реализации такого подхода. Однако прогресс на месте не стоит, и создатели Clean сделали это, причём весьма эффективно.


Очень интересно, а можно на пальцах или ссылку, где это объясняется просто и на пальцах?
Re[21]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 07.11.06 09:40
Оценка: 27 (4) :)
VoidEx,

LCR>>Единственым препятствием для была трудность практической реализации такого подхода. Однако прогресс на месте не стоит, и создатели Clean сделали это, причём весьма эффективно.


VE>Очень интересно, а можно на пальцах или ссылку, где это объясняется просто и на пальцах?


Uniqueness typing.

На пальцах:
Представим, что у нас есть функция
%%% язык типа эрланг, но аннотации типов из хаскеля.
append_char :: (File, Char) -> File.
append_char (File, Char) ->
  (use io api...).

main :: File -> (File, File).
main (file) ->
  {append_char(file, 'a'), append_char(file, 'b')}.

Если мы будем добавлять в файл символ и возвращать тот же файл, то функция append_char перестаёт быть собственно функцией и результат main зависит от того, левый или правый элемент тупла вычисляется первым. Это можно победить, если возвращать копию файла. Тогда main будет гарантированно всегда возвращать тот же самый результат. Создание новых файлов — это конечно слишком неэффективно и разумеется отметается как вариант. Но что тогда?

К счастью, побочные эффекты допустимы при некоторых ограничениях. Если можно гарантировать, что некий объект не расшарен между функциями, то изменение можно сделать прямо на месте не копируя объект. Было бы неплохо, если бы на этапе компиляции можно было бы определять уникальность аргументов и результатов функций. Но к сожалению, это неразрешимая задача (см. Теорема Райса, проблема останова и т.п.). Поэтому система типов расширяется дополнительным атрибутом UNQ, этот атрибут вставляется программером в нужных местах (где компилятор не может определить уникальность сам), а система типов отвечает за верификацию. Естественно, вывод типов также должен учитывать этот момент.

Если мы теперь напишем
append_char :: (UNQ File, Char) -> UNQ File.
append_char (File, Char) ->
  (use io api...).

main :: UNQ File -> (UNQ File, UNQ File).
main(file) ->
  {append_char(file, 'a'), append_char(file, 'b')}.

то система типов отметёт этот код как некорректный. Если же
main :: UNQ File -> (File, File).

то всё нормально.

Как гарантировать порядок вычислений? Нужно просто передать world в качестве параметра, и тип этого world должен быть помечен атрибутом UNQ. Просто и эффективно, не так ли? (хотя куча людей придерживаются мнения, что монады помощнее будут).
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[21]: Функциональное программирование для всех
От: Mikl Kurkov Россия  
Дата: 07.11.06 12:57
Оценка: 52 (1) +1
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, Lazy Cjow Rhrr, Вы писали:


LCR>>Единственым препятствием для была трудность практической реализации такого подхода. Однако прогресс на месте не стоит, и создатели Clean сделали это, причём весьма эффективно.


VE>Очень интересно, а можно на пальцах или ссылку, где это объясняется просто и на пальцах?


Вот хорошая статья про монаду IO в Haskell. Собственно идея та же — в функциях, взаимодействующих с внешним миром, добавляется еще один парметр RealWorld, также возвращаемое значение дополняется тем же значением RealWorld. Эти значения нужны только для компилятора,- чтобы обеспечить правильный порядок вызовов и не дать ему соптимизировать вызовы одной функции с одинаковыми парметрами. В статье показано как это можно сделать без всяких монад, монады же просто скрывают от программиста этот механизм и упрощают его использование.

--
Mikl
Re[22]: Функциональное программирование для всех
От: VoidEx  
Дата: 07.11.06 14:06
Оценка:
Здравствуйте, Mikl Kurkov, Вы писали:

MK>Вот хорошая статья про монаду IO в Haskell. Собственно идея та же — в функциях, взаимодействующих с внешним миром, добавляется еще один парметр RealWorld, также возвращаемое значение дополняется тем же значением RealWorld. Эти значения нужны только для компилятора,- чтобы обеспечить правильный порядок вызовов и не дать ему соптимизировать вызовы одной функции с одинаковыми парметрами. В статье показано как это можно сделать без всяких монад, монады же просто скрывают от программиста этот механизм и упрощают его использование.


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


Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Если мы будем добавлять в файл символ и возвращать тот же файл, то функция append_char перестаёт быть собственно функцией и результат main зависит от того, левый или правый элемент тупла вычисляется первым. Это можно победить, если возвращать копию файла. Тогда main будет гарантированно всегда возвращать тот же самый результат. Создание новых файлов — это конечно слишком неэффективно и разумеется отметается как вариант. Но что тогда?


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


Т.е. я правильно понял, что один из append_char изменит текущий file, а другой сделает копию?
Re[23]: Функциональное программирование для всех
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 07.11.06 15:54
Оценка:
VoidEx,

VE>Т.е. я правильно понял, что один из append_char изменит текущий file, а другой сделает копию?


Скорее всего да. 'Скорее всего' — потому что здесь легко можно вывести уникальность одного из аргументов (первого или второго, но ессно не обоих сразу) самим компилятором. Но сейчас компилятора под рукой нет, проверить не могу.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[22]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.06 00:56
Оценка: :)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

LCR>Просто и эффективно, не так ли?


Не то слово! А каой оргазм испытывает мозг при пропускании этой простоты через него!!!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Функциональное программирование для всех
От: raskin Россия  
Дата: 09.11.06 20:04
Оценка:
deniok wrote:
> Спасибо всем (отдельно Кодту за обычную содержательность). Был неправ.
> Хотел поставить себе минус, но не обнаружил такой возможности.
>
> Разаработчикам: поддержите возможность самокритики
Поднимайте старую ветку в обсуждении сайта.. Может, в этот раз..
Posted via RSDN NNTP Server 2.1 beta
Re[23]: Функциональное программирование для всех
От: BulatZiganshin  
Дата: 15.02.07 15:19
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, Mikl Kurkov, Вы писали:


MK>>Вот хорошая статья про монаду IO в Haskell. Собственно идея та же — в функциях, взаимодействующих с внешним миром, добавляется еще один парметр RealWorld, также возвращаемое значение дополняется тем же значением RealWorld. Эти значения нужны только для компилятора,- чтобы обеспечить правильный порядок вызовов и не дать ему соптимизировать вызовы одной функции с одинаковыми парметрами. В статье показано как это можно сделать без всяких монад, монады же просто скрывают от программиста этот механизм и упрощают его использование.


VE>Спасибо, про монады я читал Хотел узнать, чем решение в Clean отличается.


меня мозговой штурм на эту тему привёл к следующему выводу: есть различные варианты реализации императвиности в lazy языке. один — использовать уникальные типы (оно как раз описано в этой статье, а также используется в Clean, Mercury), второе — использование continuations (использовалось в hbc и возможно других хаскел-компиляторах; фактичсеки это тоже способ сделать нечто уникальным, только на этот раз уникальным является цепочка последующих исполняемых прцедур, передаваемая в качсетве continuation)

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


VE>Здравствуйте, Lazy Cjow Rhrr, Вы писали:


LCR>>Если мы будем добавлять в файл символ и возвращать тот же файл, то функция append_char перестаёт быть собственно функцией и результат main зависит от того, левый или правый элемент тупла вычисляется первым. Это можно победить, если возвращать копию файла. Тогда main будет гарантированно всегда возвращать тот же самый результат. Создание новых файлов — это конечно слишком неэффективно и разумеется отметается как вариант. Но что тогда?


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


VE>Т.е. я правильно понял, что один из append_char изменит текущий file, а другой сделает копию?


фактически в той статье и описано как этот вопрос решается. файл передавать туд-а-сюда не надо, достаточно найти некий механизм, гарантирующий что вызовы функций, "изменяющих мир", не будут пропущенны
Люди, я люблю вас! Будьте бдительны!!!
Re: Функциональное программирование для всех
От: mike.b Россия  
Дата: 05.04.08 10:25
Оценка: 13 (2)
Прочитал вот статью и содержимое обсуждения, но так и не нашёл ответов на мучающие меня вопросы. Возможно, кто-нибудь сможет откомментировать мои мысли?

1. Однако. Теоретически всё хорошо, на маленьких примерах всё отлично, но при обращении к большим примерам (а на Haskell их немало), то я вижу такие вещи.

1.1. Конечно, возможно, это отлично, что каждый может определить свои примитивы для control flow. Вроде монад, скобок, стрелки. Но оказывается (?) этих примитивов не хватает. Они не универсальны, и в большом проекте возникает куча собственных промежуточных абстракций, которые реализуют собственный control flow через манипулирование функциями. Можно сказать, что это отлично, что так и должно быть, ведь, это — true fp.

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

Хороший пример этого неудобства — книга Пейтона Джонса о разработке компилятора и виртуальной машины для функционального языка. Где для каждой мелкого с точки зрения функциональности дополнения приходится переписывать ВСЕ функции. Конечно, эти изменения внести можно быстро благодаря структуре языка. Но их нужно внести МНОГО.

И это черта не только примеров в этой книге. Я попробовал немножко похакать вокруг исходников Frag — приходится делать то же самое. Что я делаю не так?

1.1.1. Возможно, это поведение связано с тем, что конструируется main — 'высокоматематичный' объект. Функция. А, как известно, математические объекты никакой динамикой не обладают. И чтобы эти объекты менять, их нужно менять целиком, на всех уровнях.

1.2. Сначала в Haskell мы упорно уходим от side effects, уходим от переменных, а потом очень много кода пишем при помощи монад. Но монады — это не очень гибкий инструмент, потому что связывание функций возможно только единственным способом. Конечно, можно иметь несколько bind'ов, но это вряд ли приведёт к улучшению понимания кода. Да и как может быть заранее известно, какой именно bind понадобится, и как они должны взаимодействовать. Поэтому, для организации dataflow:

1.2.1. Нужно делать world-состояние большим, включая в него большое количество значений. Но это сводит на нет все утверждения об автоматическом распараллеливание. Вычисление в монаде строго последовательные. А монады сплошь и рядом. Непонятно в этом случае, а зачем уходить от переменных и от описания dataflow при помощи них? Да, они требуют более мощных алгоритмов автоматического распараллеливания, но эти алгоритмы дают и больше возможностей. А насчёт того, насколько это возможно, так посмотрите компиляторы Fortran и С от Intel и Sun.

1.2.2. Можно попробовать разбить все вычисления на вычисления в небольших монадках, но это увеличивает количество аргументов у функций, заставляет придумывать функции для склейки значений. Снова усложнение. Зачем, если с переменными проще?

1.2.3. Стрелка спасает, но не очень эффективно: опять же требует много дополнительного кода для манипуляции над значениями.

2. Возможно, всё хорошо, пока дело не доходит до вызова main. Вызов — же это действие — 'примени main к такому-то значению', а не описание применения. Что-то у меня в голове не сходится: мы долго бежим от того, чтобы использовать действия, и в итоге, оно оказывается чуть ли ни самой фажной частью системы. Зачем писать программы, которые никто не запускает? Как насчёт концептуальной целостности?

В чём я не прав? Надеюсь, тут есть гуру, которые смогут открыть мне глаза.
Re[5]: Функциональное программирование для всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.04.08 18:25
Оценка: :)
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

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>

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

Вообще идея приводить человеку вообще не понимающему что такое ФП примеры на ОКамле или его аналоге — это все равно, что глумиться над старушкой заставляя читать ее учебник по высшей математике.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Функциональное программирование для всех
От: Cyberax Марс  
Дата: 05.04.08 18:31
Оценка:
Здравствуйте, VladD2, Вы писали:

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

VD>Вообще идея приводить человеку вообще не понимающему что такое ФП примеры на ОКамле или его аналоге — это все равно, что глумиться над старушкой заставляя читать ее учебник по высшей математике.
Можно утешиться тем, что примеры не на K или Haskell'е
Sapienti sat!
Re[2]: Функциональное программирование для всех
От: BulatZiganshin  
Дата: 10.04.08 19:12
Оценка: +2 -2 :))) :)))
Здравствуйте, mike.b, Вы писали:

MB>1.1. Конечно, возможно, это отлично, что каждый может определить свои примитивы для control flow. Вроде монад, скобок, стрелки. Но оказывается (?) этих примитивов не хватает. Они не универсальны, и в большом проекте возникает куча собственных промежуточных абстракций, которые реализуют собственный control flow через манипулирование функциями. Можно сказать, что это отлично, что так и должно быть, ведь, это — true fp.


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

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


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

MB>Хороший пример этого неудобства — книга Пейтона Джонса о разработке компилятора и виртуальной машины для функционального языка. Где для каждой мелкого с точки зрения функциональности дополнения приходится переписывать ВСЕ функции. Конечно, эти изменения внести можно быстро благодаря структуре языка. Но их нужно внести МНОГО.


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

MB>И это черта не только примеров в этой книге. Я попробовал немножко похакать вокруг исходников Frag — приходится делать то же самое. Что я делаю не так?


я пробовал изучать C по другой книге, посящённой созданию 3d-шутеров, и тоже ни чаго не понял. что я делаю не так?

MB>1.2. Сначала в Haskell мы упорно уходим от side effects, уходим от переменных, а потом очень много кода пишем при помощи монад. Но монады — это не очень гибкий инструмент, потому что связывание функций возможно только единственным способом.


к тому же фнукции — негибкий инструмент потомушта для них предусмотрен всего один способ вызова. вот если бы f() ознаало одно, а f[] — другое, это было бы реальное преимущество перед бейсиком

MB>Конечно, можно иметь несколько bind'ов, но это вряд ли приведёт к улучшению понимания кода. Да и как может быть заранее известно, какой именно bind понадобится, и как они должны взаимодействовать. Поэтому, для организации dataflow:


вот ещё одна проблема с фукциями — как их можно писать, если заранее неизвестно какие понадобятся. ну просто ума не приложу!

MB>1.2.1. Нужно делать world-состояние большим, включая в него большое количество значений. Но это сводит на нет все утверждения об автоматическом распараллеливание.


и ещё у С недостаток — на моём денди не работает. а сосед говорил, что будет. ну не мог же мой сосед наврать!

>Вычисление в монаде строго последовательные. А монады сплошь и рядом. Непонятно в этом случае, а зачем уходить от переменных и от описания dataflow при помощи них? Да, они требуют более мощных алгоритмов автоматического распараллеливания, но эти алгоритмы дают и больше возможностей. А насчёт того, насколько это возможно, так посмотрите компиляторы Fortran и С от Intel и Sun.


а для бейсика емсть калькуятор МK-85, значит бейсик лучше!

MB>1.2.2. Можно попробовать разбить все вычисления на вычисления в небольших монадках, но это увеличивает количество аргументов у функций, заставляет придумывать функции для склейки значений. Снова усложнение. Зачем, если с переменными проще?


вот и я о том же. зачем вызывать функции, передавать им аргументы, если можно все вычисления написать самому. ну ведь проще так, чесслово!

MB>1.2.3. Стрелка спасает, но не очень эффективно: опять же требует много дополнительного кода для манипуляции над значениями.


а ещё говорят там есть классы — это уж вовсе недецкий изврат

MB>2. Возможно, всё хорошо, пока дело не доходит до вызова main. Вызов — же это действие — 'примени main к такому-то значению', а не описание применения. Что-то у меня в голове не сходится: мы долго бежим от того, чтобы использовать действия, и в итоге, оно оказывается чуть ли ни самой фажной частью системы. Зачем писать программы, которые никто не запускает? Как насчёт концептуальной целостности?


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

MB>В чём я не прав? Надеюсь, тут есть гуру, которые смогут открыть мне глаза.


на деревню дедушке Мазаю от пионерской организации. передать в сосбвтенные руки
Люди, я люблю вас! Будьте бдительны!!!
Re[4]: Функциональное программирование для всех
От: LaPerouse  
Дата: 11.04.08 06:40
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Q>>Вы плохо понимаете, что такое побочные эффекты. Если вы меняете поле в структуре, которую вам передали по указателю, то вы меняете состояние внешнего объекта — это побочный эффект. А программ на С, где такого нет, я не знаю.


VD>Это зависит исключительно от того кто и как пишет.


Все таки я тоже не припомню случая, чтобы на С вместо модификации данных, ссылка на которые приплыла на стеке, создавали измененную копию. Лишний malloc, от мысли об этом любой с-программист выпадет в осадок. Зато компиляторы ФП могут оптимизировать этот процесс и клонировать только определенные части данных.

struct A
{
int a;
}

struct B
{
int b;
}

struct S
{
A* a;
B* b;
}

S* foo(S* s)
{
struct A* newA = {s.a.a++};
struct B* newB = {s.b.b};
struct S* newS={newA, newB};
return S;
}

В фп например компилятор увидев, что newB является копией b, может сделать так:

newS = {newA, S.b}

Чтобы на С получить эту оптимизацию, надо самому следить за неизменямостью ссылки b и здесь, и в будущем (за пределами функции foo). Это и есть "автоматическое управление identity", которым так гордятся функциональщики.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[2]: Функциональное программирование для всех
От: LaPerouse  
Дата: 11.04.08 07:32
Оценка: +1
Здравствуйте, mike.b, Вы писали:

MB>Прочитал вот статью и содержимое обсуждения, но так и не нашёл ответов на мучающие меня вопросы. Возможно, кто-нибудь сможет откомментировать мои мысли?


MB>1. Однако. Теоретически всё хорошо, на маленьких примерах всё отлично, но при обращении к большим примерам (а на Haskell их немало), то я вижу такие вещи.


MB>Хороший пример этого неудобства — книга Пейтона Джонса о разработке компилятора и виртуальной машины для функционального языка. Где для каждой мелкого с точки зрения функциональности дополнения приходится переписывать ВСЕ функции. Конечно, эти изменения внести можно быстро благодаря структуре языка. Но их нужно внести МНОГО.


Цена внесения изменений не зависит от парадигмы а зависит от соблюдений/не соблюдений общепринятых норм проектирования ПО, которые и для ООП и для ФП совершенно одинаковы. Кратко их можно сформулировать так: программы должны строиться из модулей, которые могут взаймодействовать друг с другом только по строго определенным абстрактным интерфейсам.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[3]: Функциональное программирование для всех
От: m.o.b. Россия  
Дата: 15.04.08 18:19
Оценка:
LP>Цена внесения изменений не зависит от парадигмы а зависит от соблюдений/не соблюдений общепринятых норм проектирования ПО, которые и для ООП и для ФП совершенно одинаковы. Кратко их можно сформулировать так: программы должны строиться из модулей, которые могут взаймодействовать друг с другом только по строго определенным абстрактным интерфейсам.

Угу. Когда программа написана, то все её модули 'взаимодействуют друг с другом только по строго определённым абстрактным интерфейсам'. А как часто у Вас получалось сразу же придумать лучший абстрактный интерфейс для новых модулей в новой программе? А цена изменения интерфейса в процессе проектирования для ФП (кстати, ООП тут ничем не лучше ФП, да и вообще этот подход ничем не лучше, кроме толщины книг ему посвящённых) очень высока. Добавили одну переменную в состояние -> правим все функции, потому что аргументы надо протаскивать по всему графу вызовов, ну и прочие прелести. По крайней мере, мой опыт таков. И вы не думайте, что модули у меня выходили в итоге монструазные и не абстрактны, нет, я всегда стремлюсь к минимальным интерфейсам — 20 функций для меня уже слишком много.

Но на Си к итоговым хорошим интерфейсам подобраться получается гораздо быстрее, чем на Haskell, например. Понимаю, что опыта у меня не много, но опять же, небольшое изменение в уже готовую программу на Си я вношу быстро, а в программу на Haskell — долго и упорно. Хотя, кажется, что текста пишется при этом меньше. Но локальное (казалось бы) изменение расползается на код всего модуля. Я, конечно, могу быть и не правым. Но мистер Джонс патриарх же, насколько я знаю. И у него в книге всё точно так же, как и в моих попытках постичь ФП. Может быть, я чего-то воспринимаю неправильно?
Re[4]: Функциональное программирование для всех
От: Аноним  
Дата: 16.04.08 00:50
Оценка:
Здравствуйте, m.o.b., Вы писали:

MOB>Добавили одну переменную в состояние -> правим все функции, потому что аргументы надо протаскивать по всему графу вызовов, ну и прочие прелести.


Хм... а если использовать монаду State?
Re[4]: Функциональное программирование для всех
От: LaPerouse  
Дата: 16.04.08 06:18
Оценка: 1 (1) +1
Здравствуйте, m.o.b., Вы писали:

LP>>Цена внесения изменений не зависит от парадигмы а зависит от соблюдений/не соблюдений общепринятых норм проектирования ПО, которые и для ООП и для ФП совершенно одинаковы. Кратко их можно сформулировать так: программы должны строиться из модулей, которые могут взаймодействовать друг с другом только по строго определенным абстрактным интерфейсам.


MOB>Угу. Когда программа написана, то все её модули 'взаимодействуют друг с другом только по строго определённым абстрактным интерфейсам'. А как часто у Вас получалось сразу же придумать лучший абстрактный интерфейс для новых модулей в новой программе?


Редко. Рефакторить всегда приходится много.

MOB>Добавили одну переменную в состояние -> правим все функции, потому что аргументы надо протаскивать по всему графу вызовов, ну и прочие прелести.


Я не знаток хаскеля, но много раз читал, что как раз для этой цели хорошо пригодны монады.

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


MOB>Но на Си к итоговым хорошим интерфейсам подобраться получается гораздо быстрее, чем на Haskell, например. Понимаю, что опыта у меня не много, но опять же, небольшое изменение в уже готовую программу на Си я вношу быстро, а в программу на Haskell — долго и упорно. Хотя, кажется, что текста пишется при этом меньше. Но локальное (казалось бы) изменение расползается на код всего модуля. Я, конечно, могу быть и не правым. Но мистер Джонс патриарх же, насколько я знаю. И у него в книге всё точно так же, как и в моих попытках постичь ФП. Может быть, я чего-то воспринимаю неправильно?


Опять же, не будучи особым знатоком фп, выскажу кое-какие соображения по этому поводу. Классы типов + параметический полиморфизм обеспечивают приблизительно тот же уровень полиморфизма, что и интерфейсы + элементы обобщ. программирования в обычных ООП-языках. Чудес не бывает, и при изменении интерфейса и там и там приходится перепахать код с его использованием. Возможности изменения реализации, не затрагивая интерфейса и там, и там одинаковы. Поэтому я не могу понять, почему стоимость внесения изменений может быть где-то выше. Протаскивание же состояния на стеке никак не может увеличить цену внесения изменений, какая разница, к чему обращается функция/метод — к глобальному состоянию или переданному на стеке. Какая разница, чем является переменная, тип которой меняется — локальной или членом класса.
Социализм — это власть трудящихся и централизованная плановая экономика.
Re[15]: Функциональное программирование для всех
От: Dusty Россия  
Дата: 16.04.08 18:48
Оценка:
Здравствуйте, VladD2, Вы писали:

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

VE>>Можно сказать так, отличительной чертой ФЯ является то, что некоторые из них имеют отсутствие побочных эффектов.

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

Отличительной чертой птиц (среди других позвоночных) является способность летать.
Что будем делать со страусами/пингвинами, с одной стороны; и с птеродактилями/летучими мышами — с другой?
Re[16]: Функциональное программирование для всех
От: VoidEx  
Дата: 16.04.08 22:13
Оценка:
Здравствуйте, Dusty, Вы писали:

Тут термин неверно мной подобран. Точнее его двояко в жизни используют. Ибо формально способность летать — не отличительная черта птиц. С другой стороны, если кого-то спросить "что за животные такие — птицы", самым простым ответом будет, что они летают. Хотя можно сказать "двулапые с перьями"
Re[17]: Функциональное программирование для всех
От: Dusty Россия  
Дата: 17.04.08 20:09
Оценка:
Здравствуйте, VoidEx, Вы писали:

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


VE>Тут термин неверно мной подобран.

Неверно, но правильно В смысле — именно наналогия с птицами позволяет понять, что же такое ФЯ в отличие от ИЯ.

VE>Ибо формально способность летать — не отличительная черта птиц.

Да, верно.
Но с другой стороны, у биологов есть список из формальных признаков птиц — т.н. "синдром"; семь штук, кажется (или это у млеков 7, а у птиц 6? не помню).
И если посмотреть на этот список, то большинство признаков являются либо обеспечением возможности полета (маховое перо — пуховое перо появилось еще у предшественников птиц); либо оптимизацией под полет (теплокровность — повышенная энергетика; килевая кость — прикрепление мускулов для движения крыльев и т.д.) У страусов и пингвинов — хоть они и не летают — все эти формальные признаки сохранились (из-за чего их и считают птицами); но уже не служат для полета.

С ФЯ почти то же самое. Существует целый спектр оптимизаций в дизайне языков, упрощающих написанием на нем функциональных программ. Если в языке представлено достаточно большое количество таких оптимизаций, то он "поддерживает функциональную парадигму". Если, он не поддерживает кроме функциональной парадигмы других — то это ФЯ (иначе — это "гибридный" язык; вещь, в животном мире не встречающаяся).

VE>С другой стороны, если кого-то спросить "что за животные такие — птицы", самым простым ответом будет, что они летают.

Угу. Ибо — как в анекдоте про верблюженка — "а нафига нам все это в зоопарке?".
Re[3]: Функциональное программирование для всех
От: BulatZiganshin  
Дата: 19.04.08 17:36
Оценка: +1
Здравствуйте, LaPerouse, Вы писали:

LP>Цена внесения изменений не зависит от парадигмы


зависит, как и стоимость самого программирования. языки развивиаются как раз в направлении увеличения компонентности программирования, ООП например исключительно в этом и состоит
Люди, я люблю вас! Будьте бдительны!!!
Re: Функциональное программирование для всех
От: SuperRockStar  
Дата: 02.12.08 07:32
Оценка: :))
Здравствуйте, Линкер Николай (перевод), Вы писали:

ЛНП>Статья:

ЛНП>Вячеслав Ахмечет. Функциональное программирование для всех
Автор(ы): Вячеслав Ахмечет
Дата: 16.09.2006
Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.


ЛНП>Авторы:

ЛНП> Линкер Николай (перевод)

ЛНП>Аннотация:

ЛНП>Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.

После прочтения статьи вообще потерял интерес к ООП. Хочу программировать на ФЯ!
ООП — old stuff . ФЯ — rocks!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.