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