Comments 24
скажите, а именование переменных в виде одной или малого количества символов — это характеристика языка или просто привычка? я серьезно спрашиваю, без сарказма, интересно
+1
Если переменная встречается всего на двух строчках, то зачем ей длинное имя?
+1
характеристикой это назвать сложно, скорее (насколько я успел заметить) некоторая негласная договоренность программистов. Максимально полно именуются только верхнеуровневые функции. Может быть это подсознательная мысль: «ФП-код должен быть коротким» покоя не дает? :)
Переменные в лямбдах вообще обычно одним или двумя символами обозначают. Ну собственно, так же как и for (int i = 0… )
Переменные в лямбдах вообще обычно одним или двумя символами обозначают. Ну собственно, так же как и for (int i = 0… )
0
лямбды и итераторы цикла — это понятно
но в вышеприведенном коде такой подход — везде, я про это и спросил, поскольку с языком практически не знаком, а пытаться разобраться на сплошных r, t, e, l — просто не могу
но в вышеприведенном коде такой подход — везде, я про это и спросил, поскольку с языком практически не знаком, а пытаться разобраться на сплошных r, t, e, l — просто не могу
+1
Клево. Тема теорката вообще интересна. :) (правда, я его не осиливаю)
Нельзя ли как-нибудь убрать побочные эффекты из Printer? (Пусть возвращает строку, которую затем можно будет вывести куда угодно.) Наверняка там (в F#) есть какой-нибудь «монадический катаморфизм» + монада Writer.
> P.S. Не знаю, стоит ли переносить в какой-то коллективный блог, все-таки тема специфическая.
Ну конечно стоит. Катаморфизм полезен же!
Следующая статья, наверное, будет о zipper'ах? :) Тоже очень полезная штука.
Нельзя ли как-нибудь убрать побочные эффекты из Printer? (Пусть возвращает строку, которую затем можно будет вывести куда угодно.) Наверняка там (в F#) есть какой-нибудь «монадический катаморфизм» + монада Writer.
> P.S. Не знаю, стоит ли переносить в какой-то коллективный блог, все-таки тема специфическая.
Ну конечно стоит. Катаморфизм полезен же!
Следующая статья, наверное, будет о zipper'ах? :) Тоже очень полезная штука.
0
Да что-то я не думаю, что многим понравится.
— Нельзя ли как-нибудь убрать побочные эффекты из Printer? (Пусть возвращает строку, которую затем можно будет вывести куда угодно.)
— Она ровно это и делает — функция sprintf — это и есть «печать в строку», так что функция Printer имеет тип Expr -> string :)
— Нельзя ли как-нибудь убрать побочные эффекты из Printer? (Пусть возвращает строку, которую затем можно будет вывести куда угодно.)
— Она ровно это и делает — функция sprintf — это и есть «печать в строку», так что функция Printer имеет тип Expr -> string :)
0
> Да что-то я не думаю, что многим понравится.
А о чем еще писать? Очередное «я вот напейсал вот такой быдлокод, зацените результаты воздействия синдрома туннельного зрения»? (конечно, не все статьи на хабре такие, но много.)
/me ушел негодовать.
> Она ровно это и делает — функция sprintf — это и есть «печать в строку», так что функция Printer имеет тип Expr -> string :)
Млин, я уже путаю printf и sprintf! O_O
А о чем еще писать? Очередное «я вот напейсал вот такой быдлокод, зацените результаты воздействия синдрома туннельного зрения»? (конечно, не все статьи на хабре такие, но много.)
/me ушел негодовать.
> Она ровно это и делает — функция sprintf — это и есть «печать в строку», так что функция Printer имеет тип Expr -> string :)
Млин, я уже путаю printf и sprintf! O_O
+3
Насчет суммирования элементов списка — а что если написать так:
myList |> Seq.of_list |> Seq.reduce (fun x y -> x + y)
myList |> Seq.of_list |> Seq.reduce (fun x y -> x + y)
0
Что-то у меня противоречивые чувства по поводу поголовного переписывания рекурсии в CPS. Мы размениваем стек на выделение памяти в куче, причём сборщик мусора не может подобрать ни одно замыкание до завершения всей функции. Понятно, что CLR больнее бьёт по рукам за переполнение стека, но CPS-преобразование зачастую работает как обфускатор.
Спасибо за статью, надо сделать ещё один набег на бананы с колючей проволокой.
Спасибо за статью, надо сделать ещё один набег на бананы с колючей проволокой.
0
Спасибо, хорошая статья. Узнал что-то новое.
Но думаю, что стоит добавить при переходе от левосторонней свертке к правосторонней, что мы все равно и по любому теряем в памяти: fold_left бежит по списку и применяет функцию, а fold_right бежит по списку, запоминает его, а затем бежит обратно и применяет функцию. Просто в первом случае он запоминает его в стеке, а во втором в куче, но порядок расхода памяти одинаковый — чуда нет. При работе с деревом так же создается его копия.
Но думаю, что стоит добавить при переходе от левосторонней свертке к правосторонней, что мы все равно и по любому теряем в памяти: fold_left бежит по списку и применяет функцию, а fold_right бежит по списку, запоминает его, а затем бежит обратно и применяет функцию. Просто в первом случае он запоминает его в стеке, а во втором в куче, но порядок расхода памяти одинаковый — чуда нет. При работе с деревом так же создается его копия.
0
вы правы конечно.
что ж, чудеса в нашем мире случаются нечасто :)
что ж, чудеса в нашем мире случаются нечасто :)
0
В отличие от энергичного F# в ленивом Haskell благодаря deforestation связка генератор — map/filter — foldr может даже не порождать списки. И, разумеется, foldr не бежит по списку, запоминая его. В этом нет никакой необходимости — достаточно вспомнить, что foldr просто заменяет (::) на операцию, а [] на стартовый элемент. Если операция ленива (не +), то foldr очень даже выручает.
+2
Вот эта статья раньше была в русской вики
traditio.ru/wiki/Катаморфизм
traditio.ru/wiki/Катаморфизм
0
Sign up to leave a comment.
Катаморфизм в F#