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<#)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.