LINUX.ORG.RU

Вышел 2-й выпуск журнала «Практика функционального программирования»

 , , ,


1

0

Вышел в свет второй выпуск журнала «Практика функционального программирования».

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

Первые четыре статьи — Дмитрия Зуйкова, Дмитрия Астапова, Сергея Зефирова в соавторстве с Владиславом Балиным, и Алексея Отта — вытаскивают на поверхность «кухню» нескольких компаний. Статьи демонстрируют, что функциональные языки находят применение в промышленном программировании в самых разных нишах. Конечно, использование «нестандартных» языков накладывает на проекты некоторые сложно оценимые риски, и далеко не все из них рассмотрены в статьях. Но если статьи этого номера позволят развеять хоть часть сомнений, мифов и предрассудков и поднять дискуссию о применимости функциональных языков в промышленном программировании на новый уровень, мы будем считать свою задачу выполненной.

Статья Александра Самойловича рассматривает создание на языке Erlang игрушечного, но практичного проекта — рекурсивного многопоточного обходчика сайтов. К третьему выпуску журнала мы планируем подготовить ещё несколько статей про Erlang.

Завершающая статья Романа Душкина в большей степени ориентирована на теорию: она познакомит вас с концепцией алгебраических типов данных (АТД) в Haskell и других функциональных языках.

>>> Подробности

★★★★★

Проверено: maxcom ()
Последнее исправление: maxcom (всего исправлений: 1)
Ответ на: комментарий от r

> При императивном подходе ты бы сначала что-то сделал а потом воспринял причину действий.

Это здец. У тебя какое-то свое определение императивности, причем оно как-то влияет на восприятие человека.

> Классический черный ящик. Реакция на входной сигнал.

Инкапсуляция - это не прерогатива ФП. Вызов метода объекта - это тоже черный ящик и тоже реакция на входной сигнал. Библиотечные функции и объекты - тоже черный ящик.

> Императивно - это значит ты бы приготовился отдернуть руку без наличия причины, а потом когда появился огонь - отдернул бы ее. А вдруг бы огонь не появился?

> При императивном подходе ты бы сначала что-то сделал а потом воспринял причину действий.

Вы можете мне дать свое определение императивности без говноаналогий?

anonymous
()
Ответ на: комментарий от anonymous

> Ты так говоришь, как будто монады - это нечто чужеродное в Хаскелле. > Нет, это костыль для обертки побочных эффектов.

Дурак ты, Василий. RTFM, в том числе о монадах в математике.

anonymous
()
Ответ на: комментарий от anonymous

> Императивность не означает бездумность. Как вообще связано создание алгоритма, целеполагание человека и представление этого алгоритма в голове?

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

pitekantrop ★★★
()
Ответ на: комментарий от psv1967

> ну почему очень забавно бывает, вот свежачок сегодня читал :)

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

anonymous
()
Ответ на: комментарий от r

> Императивность обозначает описание фокус на том _как_ нужно достич цели а не фокус на том _что_ такое цель по определению.

> При чем тут создание? Алгоритм можно описать двумя способами: в качестве последовательности шагов и в качестве определения того что есть результат.

Да. И причем здесь бездумность?

anonymous
()
Ответ на: комментарий от r

> У бульдозера есть гусеницы - значит бульдозер - это танк? В корень смотреть надо а не на внешние проявления.

Я про то же.

anonymous
()
Ответ на: комментарий от anonymous

> Дурак ты, Василий. RTFM, в том числе о монадах в математике.

Да, теория категорий, функторы и прочий базз-ворд. И я в курсе про другие применения монад.

anonymous
()
Ответ на: комментарий от anonymous

У тебя какое-то свое определение императивности, причем оно как-то влияет на восприятие человека.

Это у тебя какое то свое.

код:

{
x = 5 + 2
return f(x)
}

f я определю позже. Нука «выполни» код императивно?

Инкапсуляция - это не прерогатива ФП.

Инкапсуляция тут не при чем. forget(oop), consult(теория систем). Черный ящик определяет выходные сигналы как функцию от входных. Вот твоя инкапсуляция:

class X {
   private int x = 0;
   void inc() {x++}
   int zet(int y) {return x + y};
}
Инкапсулирован? По самое нехочу. Но нефига не черный ящик - это класс c недетерминированным поведением. Результат вызова zet зависит от предидущей истории. И видя в коде X.zet(5) - ты никогда не предскажешь результат.

Вы можете мне дать свое определение императивности без говноаналогий?

http://ru.wikipedia.org/wiki/Императивное_программирование

r ★★★★★
()
Ответ на: комментарий от psv1967

> вот мы и узнали как мыслят "императивные программисты" :)

Ну, и "теоретический" спор у вас тут, как погляжу :)

Логика - изобретение человеческого разума. Мозг так _не_ работает. Функциональщина - такое же изобретение. В природе ее нет. Впрочем, мне думается, что императивщина - это тоже абстракция. Человеческий мозг устроен иначе, и работает совершенно на других принципах (хорошо бы знать каких...).

dave ★★★★★
()
Ответ на: комментарий от pitekantrop

> Приготовление еды по рецепту, т.е. императивное, означает бездумность.

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

> А вот чтобы составить рецепт, надо подумать, что надо сделать, чтобы получить результат. Т.е. появятся мысли типа "для блюда мне нужна варёная картошка, поэтому надо её почистить и закипятить воду".

составить алгоритм все-таки надо, прежде чем его использовать, только причем здесь это?

anonymous
()
Ответ на: комментарий от anonymous

> Да, теория категорий, функторы и прочий базз-ворд. И я в курсе про другие применения монад.

Тогда при чем тут "монады - это костыль к эффектам"? Два в корне неверных утверждения в одном предложении.

anonymous
()
Ответ на: комментарий от anonymous

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

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

psv1967 ★★★★★
()
Ответ на: комментарий от dave

> Логика - изобретение человеческого разума. Мозг так _не_ работает. Функциональщина - такое же изобретение. В природе ее нет. Впрочем, мне думается, что императивщина - это тоже абстракция. Человеческий мозг устроен иначе, и работает совершенно на других принципах (хорошо бы знать каких...).

ну нейрональная сетка реализует банальный PCA :)

psv1967 ★★★★★
()
Ответ на: комментарий от anonymous

> И причем здесь бездумность?

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

pitekantrop ★★★
()
Ответ на: комментарий от r

> Это у тебя какое то свое.

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

> Но нефига не черный ящик - это класс c недетерминированным поведением.

Если сравнивать с инстинктами, то да, они не черный ящик, всегда проявляются по-разному. Кстати функция rand() - это черный ящик? :)

anonymous
()
Ответ на: комментарий от anonymous

> Два в корне неверных утверждения в одном предложении.

Таки, а разве они не костыль, разве в хаскелле есть присваивание? :)

anonymous
()
Ответ на: комментарий от psv1967

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

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

anonymous
()
Ответ на: комментарий от anonymous

Да. И причем здесь бездумность?

При том что в последнем случае действия для достиджения результата плавно проистекают из необходимости - то есть делают on-demand. А в императивном делаются заранее.

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

Чтобы напримере - это непаскалевская реализация if.

x = 0 if (x != 0 && 10 / x == 5) ...

Перепишем это на императивном и функциональном псевдокоде:

Императивный:

x = 0
cond1 = x != 0
cond2 = 10 / x = 5
//&&
c = cond1 == cond1 == TRUE
//if
on c exec thencode

В чистом _императивном_ подходе тебе бы надо было вычислить 10 / x, до того как проверять && - и все бы улетело к чертовой матери. На функциональном псевдокоде

x = 0
on cond1
  on cond2
    exec thencode
where 
 cond1 = x != 0
 cond2 = 10 / x = 5 

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

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

Так вот _задумываемость_ - называется call-by-name - одно из основных свойств функциональных языков. И пример «как в if» вот тебе на скале:

scala> def f(s:String, x: =>Int) = if (s == "do") println(x) else println("nope")
f: (String,=> Int)Unit

scala> f("do", 10/0)
java.lang.ArithmeticException: / by zero

scala> f("dont", 10/0)
nope

r ★★★★★
()
Ответ на: комментарий от anonymous

> Таки, а разве они не костыль, разве в хаскелле есть присваивание? :)

Хотелось бы поподробнее: 1. Почему монады являются костылями (не только в применении к IO, но и вообще) 2. Почему нельзя обойтись без присваивания 3. Как бы обходились костыли, будь в Haskell присваивание Иными словами попробуйте доказать, что мозговитые парни, разрабатывавшие Haskell, потратили 20 лет впустую.

anonymous
()
Ответ на: комментарий от anonymous

>Кстати функция rand() - это черный ящик? :)

С точки зрения теории систем - нет.

>Если сравнивать с инстинктами, то да, они не черный ящик, всегда проявляются по-разному


У одних и тех же индивидов - одинаково.

r ★★★★★
()
Ответ на: комментарий от Kuka

>На Эрланге они не потому, что он функциональный, а потому, что он Эрланг. Мощная платформа, заточенная под concurrent programming, востребованная в телекоме, для которой функциональные плюшки - вторичны.

Неплохо бы почитать чуть дальше "Introduction" учебника языка, прежде чем газифицировать лужи

Led ★★★☆☆
()
Ответ на: комментарий от anonymous

>Ты точно знаешь, что такое инстинкты?

А что - толковый словарь имеет версии этого определения?

r ★★★★★
()
Ответ на: комментарий от r

> Так вот _задумываемость_ - называется call-by-name - одно из основных свойств функциональных языков. И пример "как в if" вот тебе на скале:

_Задумываемость_ (call-by-name) была впервые в наимперативнейшем Algol-60. И приводила она к тому, что аргументы вычислялись по нескольку раз, при каждом вызове. А вот в хаскелле, клине - используется call-by-need - там результаты momoiziлизь. И кстати, ленивые вычисления не во всех фп есть - в ml ее нет, в scheme - нет, там строгий порядок вычислений.

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

anonymous
()
Ответ на: комментарий от r

> А что - толковый словарь имеет версии этого определения?

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

anonymous
()
Ответ на: комментарий от anonymous

>_Задумываемость_ ...


И какое отношение этот исторический экскурс имеет к "императивности" мышления?



r ★★★★★
()
Ответ на: комментарий от Kuka

>> функциональные языки находят применение в промышленном программировании в самых разных нишах.

> Поднять дискуссию о применимости функциональных языков в промышленном программировании на новый уровень не удалось.

Функциональщина, знай свое место на кухне^W^W !

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

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

Да и еще: DSL-ки имхо ваяютс на функциональных языках (и лиспе) не из-за их функциональности, а из-за наличия алгебраических типов данных + паттерн матчинга (в лиспе есть АТД "для бедных").

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от tailgunner

> Что-то похожее, да. Только уже доведенное до ума и сравненное по скорости с Си или Фортраном, а то фраза "I have tested these routines, but not extensively" как бы намекает, что проект очень молодой :)

ИМХО функциональный язык без суперкомпилятора не сможет должным образом конкурировать с С/С++

При наличии оного -- вполне возможно. Однако, суперкомпилятор надо подталкивать ручками -- как я читал, ряд суперкомпиляторов умеет из тупого алгоритма матчинга подстроки делать алгоритм КМП *при условии, что искомая подстрока константна* -- но для того, чтобы догадаться, что это надо делать почти всегда, вероятно, нужен программист.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от ugoday

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

Это некоммутирующие операции. Масло по горячей сковородке растекается не так, как по холодной.

Заодно попробуй записать алгоритм "яишница" чисто функционально, посмотрим, что за монстр получится.

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Заодно попробуй записать алгоритм «яишница» чисто функционально, посмотрим, что за монстр получится.

Гыыы:

data EggState = Raw | Broken | Fryed deriving (Show)

data Eggs = Eggs EggState Int deriving (Show)

data PanState = Oiled | Dry deriving (Show)

data PanTemp = Hot | Cold deriving (Show)

data Pan = Pan PanTemp PanState deriving (Show)

omelet e p = fry (break e) (heat $ oil p)
    where
        break (Eggs Raw x) = Eggs Broken x
        break e@(Eggs Broken x) = e -- yahh, already broken
        break _ = error "you mean 'again'?"
        heat (Pan Cold x) = Pan Hot x
        heat p = p
        oil (Pan x Dry) = Pan x Oiled
        oil p = p
        fry (Eggs Broken x) p@(Pan Hot Oiled) = (Eggs Fryed x, p)
        fry _ (Pan Hot Oiled) = error "what are you gonna do with these eggs?"
        fry _ _ = error "on _that_ pan?"

Main> omelet (Eggs Raw 5) (Pan Cold Dry)
(Eggs Fryed 5,Pan Hot Oiled)            

--реюзнем сковороду

let (o,p) = omelet (Eggs Raw 5) (Pan Cold Dry) in case omelet (Eggs Raw 3) p of (o2, p2) -> ([o,o2],p2)
([Eggs Fryed 5,Eggs Fryed 3],Pan Hot Oiled)

--а теперь два раза

Main> let (o,p) = omelet (Eggs Raw 5) (Pan Cold Dry) in omelet o p

Program error: you mean 'again'?

:))

PS: Да я люблю пролог:)

r ★★★★★
()
Ответ на: комментарий от r

Ресторанное обслуживание:)

Main> foldl (\(l,p) e -> case omelet e p of (e,p) -> (e:l,p)) ([], Pan Cold Dry) [Eggs Raw 2, Eggs Raw 4, Eggs Raw 5]
([Eggs Fryed 5,Eggs Fryed 4,Eggs Fryed 2],Pan Hot Oiled)

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> ИМХО функциональный язык без суперкомпилятора не сможет должным образом конкурировать с С/С++

даже если это и так, ФП сможет конкурировать с perl/python/ruby/php и более 9000 других язычков.

С(без С++) и ФП не конкуренты по другой причине, они занимают совершенно разные ниши.

ugoday ★★★★★
()
Ответ на: комментарий от r

По версии гуглотранса:

Данные EggState = Raw | повреждении | Fryed вывода (Show) 
 Данные Яйца Яйца EggState = Int вывода (Show) 
 Данные PanState = Промасленная | Сухой вывода (Show) 
 Данные PanTemp = Горячая | Холодная вывода (Show) 
 Данные = Пан Пан PanTemp PanState вывода (Show) 
 Омлет E P = СРЮ (перерыв е) (тепло нефть $ P) 
    где 
       Перерыв (яйца Raw X) = Яйца Broken X 
       Перерыв E @ (яйца Broken X) = E - Yahh, уже сломанной 
       Перерыв _ = ошибка "Вы имеете в виду" еще раз "? 
       тепла (Pan Холодная X) = X Пан Hot 
       тепла P = P 
       Нефть (Pan X сухой) X = пан Промасленная 
       масла P = P 
       СРЮ (яйца Broken X) P @ (Pan Горячая Промасленная) = (яйца Fryed X, P) 
       СРЮ _ (Pan Горячая Промасленная) = ошибка "Что ты собираешься делать с этими яйцами?" 
        
       СРЮ _ _ = ошибка "на _that_ Пэн?

Чуть чуть доработать и будет программа на почти человеческом языке.

ugoday ★★★★★
()
Ответ на: комментарий от r

> И какое отношение этот исторический экскурс имеет к "императивности" мышления?

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

anonymous
()
Ответ на: комментарий от r

> С точки зрения теории систем - нет.

Т.е. хаскелл нельзя считать черным ящиком, потому что там есть rand?

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> (в лиспе есть АТД "для бедных")

В каком лиспе и в каком виде есть ADT для бедных?

anonymous
()
Ответ на: комментарий от www_linux_org_ru

> Это некоммутирующие операции. Масло по горячей сковородке растекается не так, как по холодной.

Растекается, да, по разному. И что, я не могу налить масла на горячую сковородку? Или на холодную?

> Заодно попробуй записать алгоритм "яишница" чисто функционально, посмотрим, что за монстр получится.

Чем оно будет монстрее аналогичного императивного описания?

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

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

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

Поясни, как это они "заставляют".

pitekantrop ★★★
()
Ответ на: комментарий от r

> let (o,p) = omelet (Eggs Raw 5) (Pan Cold Dry) in case omelet (Eggs Raw 3) p of (o2, p2) -> ([o,o2],p2)

case с одной альтернативой как-то странно выглядит :)

let (o,p) = omelet (Eggs Raw 5) (Pan Cold Dry); (o2,p2) = omelet (Eggs Raw 3) p in ([o,o2],p2)

pitekantrop ★★★
()
Ответ на: комментарий от r

Сюда просто просится монада State. :)

import Control.Monad.State

data EggState = Raw | Broken | Fryed deriving (Show)

data Eggs = Eggs EggState Int deriving (Show)

data PanState = Oiled | Dry deriving (Show)

data PanTemp = Hot | Cold deriving (Show)

data Pan = Pan PanTemp PanState deriving (Show)

omelet :: Eggs -> Pan -> (Eggs, Pan)
omelet e p = fry (break e) (heat $ oil p)
    where
      break (Eggs Raw x) = Eggs Broken x
      break e@(Eggs Broken x) = e -- yahh, already broken
      break _ = error "you mean 'again'?"
      heat (Pan Cold x) = Pan Hot x
      heat p = p
      oil (Pan x Dry) = Pan x Oiled
      oil p = p
      fry (Eggs Broken x) p@(Pan Hot Oiled) = (Eggs Fryed x, p)
      fry _ (Pan Hot Oiled) = error "what are you gonna do with these eggs?"
      fry _ _ = error "on _that_ pan?"

omelet' :: Eggs -> State Pan Eggs
omelet' e = do p <- get
               let (o, p') = omelet e p
               put p'
               return o
Один омлет:
Main> runState (omelet' $ Eggs Raw 3) $ Pan Cold Dry
(Eggs Fryed 3,Pan Hot Oiled)
Два на одной сковородке:
Main> runState (do o1 <- omelet' $ Eggs Raw 3; o2 <- omelet' $ Eggs Raw 2; return (o1, o2)) $ Pan Cold Dry
((Eggs Fryed 3,Eggs Fryed 2),Pan Hot Oiled)
Ставим на поток:
Main> runState (mapM omelet' [Eggs Raw 4, Eggs Raw 2, Eggs Raw 3]) $ Pan Cold Dry
([Eggs Fryed 4,Eggs Fryed 2,Eggs Fryed 3],Pan Hot Oiled)

pitekantrop ★★★
()
Ответ на: комментарий от pitekantrop

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

Речь шла совсем не об этом, а о том, как он воспринимает алгоритмы, что для него более естественнее - императивное или функциональное алгоритмическое "мышление".

Для человека естественно наличие состояний - identity и мутабельных объектов, данных. Когда мы откусываем яблоко - оно для нас остается тем же самым (identity), но только изменяет свое состояние. Для человека естественнено описывать процесс последовательностью действий, где каждое действие ведет к изменению "мира", пример с яичницой это наглядоно показывает.

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

Вы только что описали up-down методологию разработки программ, а она тут совершенно не при чем. С ее помощью можно точно также "декларативно" писать императивные программы.

На первом этапе (ага, нам нужно приготовить омлет, для этого надо): cook_omlet () { pan p; eggs e;

oil_pan(p); heat_pan(p); break_eggs(e); salt(e); }

(Так чтобы разбить яйца нам нужно:) break_eggs(eggs e) { ... } И тд.

anonymous
()
Ответ на: комментарий от anonymous

млятское форматирование. :(

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

Речь шла совсем не об этом, а о том, как он воспринимает алгоритмы, что для него более естественнее - императивное или функциональное алгоритмическое «мышление».

Для человека естественно наличие состояний - identity и мутабельных объектов, данных. Когда мы откусываем яблоко - оно для нас остается тем же самым (identity), но только изменяет свое состояние. Для человека естественнено описывать процесс последовательностью действий, где каждое действие ведет к изменению «мира», пример с яичницой это наглядоно показывает.

Приготовление яичницы по поваренной книге при условии наличии плиты, посуды и необходимых продуктов особых умственных усилий не требует. > Поэтому сначала речь шла о решении человеком задачи «утолить чувство голода», для чего может потребоваться пожарить яичницу, купить продукты, сходить в столовую, развести костёр и т.д. В процессе решения таких задач человек опирается на свой опыт и знания об окружающем мире: «если сделать это, то получится это, но для этого необходимо то-то и то-то». Т.е. вполне себе функциональное мышление.

Вы только что описали up-down методологию разработки программ, а она тут совершенно не при чем. С ее помощью можно точно также «декларативно» писать императивные программы.

На первом этапе (ага, нам нужно приготовить омлет, для этого надо):

cook_omlet () { 
   pan p; eggs e;
   oil_pan(p); 
   heat_pan(p); 
   break_eggs(e); 
   salt(e); 
}
(Так чтобы разбить яйца нам нужно:)
break_eggs(eggs e)  { 
   ... 
}
И тд.

anonymous
()
Ответ на: комментарий от anonymous

> Речь шла совсем не об этом, а о том, как он воспринимает алгоритмы, что для него более естественнее - императивное или функциональное алгоритмическое "мышление".

Это ты уже сейчас тему меняешь. Речь шла о бытовом мышлении. Мой ответ с яичницой был на вот эту фразу:

> Мы мыслим императивно - весь наш быт представлен последовательностями действий.

pitekantrop ★★★
()
Ответ на: комментарий от anonymous

> Для человека естественнено описывать процесс последовательностью действий, где каждое действие ведет к изменению "мира", пример с яичницой это наглядоно показывает.

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

pitekantrop ★★★
()

Скажите, это топик о функциональном программировании? Как мне приготовить яичницу с помидорами?

tailgunner ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> записать алгоритм "яишница" чисто функционально

Должно быть что-то вроде этого:

Яишница --- яйца пожаренные на сковородке

Жарка --- приготовление разбитых яиц на годной сковородке

Годная сковородка --- нагретая сковородка с налитым маслом

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

Как то так. Уж всяко человечнее чем императивное:

выделить память для счётчика количества яиц

инкрементировать счётчик количества яиц

зачистить память от более ненужного счётчика

ugoday ★★★★★
()
Ответ на: комментарий от pitekantrop

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

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

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

> Должно быть что-то вроде этого:

> Яишница --- яйца пожаренные на сковородке

> Жарка --- приготовление разбитых яиц на годной сковородке

> Годная сковородка --- нагретая сковородка с налитым маслом

> Разбитие яиц --- разрушение яйца с попаданием белка и желтка на годную сковородку, а скорлупы --- в мусорное ведро.

> выделить память для счётчика количества яиц

> инкрементировать счётчик количества яиц

> зачистить память от более ненужного счётчика

Да уж. Вы из императивных только си знаете?

В императиве это будет очень просто:

поставить сковородку на огонь

налить масло в сковороду

рабить яйца

посолить

anonymous
()
Ответ на: комментарий от tailgunner

реализуешь простейший DSL под виртуальной машиной. Заливаешь VM в мозг кухонного робота и пишешь скрипт "приготовить яичницу с помидорами".

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

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

что в словах "лучше будет смотреться" для вас неясно?

anonymous
()
Ответ на: комментарий от anonymous

В императиве это будет очень просто: [code]

поставить сковородку на огонь

налить масло в сковороду

рабить яйца

посолить [/code]

Не нашёл в твоём примере объектов с изменяемым состоянием и разрушающих присвоений. Без этого "императивная" программа выглядит слишком декларативно.

ugoday ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.