-
Notifications
You must be signed in to change notification settings - Fork 3
Open
Description
Андрей Иванов:
В прошлый раз я, как мне показалось, начал немного не с того )
с частностей и конкретики )
и чтобы оправдать "про ФП" сегодня хочу пообщее )
кто знает лямбда-исчисление? есть такие?
[9:01:40 PM] ilya korotkov:
видимо нет)
[9:01:58 PM] Андрей Иванов:
хорошо, глубоко не буду, поверхностно пробегусь.
[9:02:08 PM] Danila Litvinov:
я знаю
[9:02:10 PM] Андрей Иванов:
это математическая абстракция.
вводится понятие терма
терм - это символ, лямбда абстракция или аппликация одного терма к другому
и лубая навороченная комбинация из этих элементов - тоже терм
термы могут редуцироваться по определенным правилам (преобразовываться)
и после преоборазований оставаться также термами
если терм нельзя преобразовать, то говорят что он в нормальной форме
мы чуть опустимся от простого нетипизированного лямблда исчисления ближе к земле )
вот терм 1 + 2
редуцируется в 3
(1 + 2) + (3 + 4) в 10
[9:05:20 PM] Liscript-bot:
10
[9:05:37 PM] Андрей Иванов:
правильно )
[9:05:44 PM] Anton Chikin:
Тэкс
пока похоже на примеры из средней школы :)
[9:06:11 PM] Igor Lyskov:
не мешай
[9:06:15 PM] ilya korotkov:
))
[9:06:24 PM] Андрей Иванов:
> Anton Chikin
> пока похоже на примеры из средней школы :)
пожалуйста, не мешайте играть в песочнице.
и теория лямбда исчисления утверждает много важные ыактов и теорем
например, что независимо от порядка редукции нормальная форма будет одна и та же
то есть, мы можем редуцировать терм любым образом, и если придем к концу - то результат будет один
не важен порядок редукции подтермов
выше в примере с двумя скобками нам все равно какую раньше редуцировать - левую или праввую
а это значит, что нет строгого порядка редукции
и мы можем отдать разные термы на редукцию разным процессорам - машинам
распараллелить вычисления
[9:09:21 PM] ilya korotkov:
а вот это интересно
[9:09:43 PM] Андрей Иванов:
потому что при редукции термов выполняются только чистые операции-преобразования
и факт редукции одного подтерма не влияет на редукцию другого
в лямбда-исчислении нет чисел и операций на них, но мнокие расширенные конструкции ипзоморфны (имеют те же свойства)
и само лямбда-исчисление по себе не используется на практике, но позволяет доказывать математически свойства программ
то есть чистое ФП - это абстракция, изоморфная лямбда исчислению
и в чистом ФП (а бывет разное )) вся программа - это один большой терм
и интерпретатор его редуцирует и возвращает результат
и отсюда все следствия - отсутствие изменяемогно состояния, ввода-вывода посреди редукции, побочных эффенктов и т.п.
только терм на входе - терм на выходе
в принципе, формульный калькулятор похож по модели
только есть возможность строить более мощные абстракции, вводить функции и т.п.
но для программирования такая абстракция не совсем удобна
и реальные ФЯ иду разными путями
есть путь хаскеля - он сохранил семантику чистого ФП
но для общения с миром и побочных эффектов вводятся понятия IOмонады например
пара слов об этом )
при начале работы программ получает на вход экземпляр внешнего мира ) думайте об этом абстракно
и при любых действиях ввода-вывода это действие возвращает на новый экземпляр мира - с выполненным действием
так думает компилятор и это позволяет оставить чистоту в языке и получить ввод-выводл
другие языки пошли другим путем
ilya tazitdinov joined group via invite link
[9:18:58 PM] Андрей Иванов:
рони отказалить от полной функцйиональной чистоты
например, Liscript/Scheme
можно приновать-читать пос\реди вычислений (редукций)
можно менять внешнее состояние
можно открывать окошки и там что-то рисовать
[9:20:12 PM] ilya korotkov:
а что монад в scheme нет?
[9:20:35 PM] Андрей Иванов:
монады IO ytn
нет
но абстракцию монады списка нарисовать можно
так вот, многие ФЯ не являются чистыми
F# тот же
фактически, чистых не так много - хаскель, клеан и авсякие теорем пруверы типа Кок Агда Идрис и т.п.
но за отказ от чистоты приходится платить
инапример, мы теперь не можем в люббьой ситуации быть уверены, что нам не важен порядок редукции терма
и не можем закрывая глаза параллелить прогцессы
нужны специальные уточнения
нол это - компромисс
и тут приходим к философскому вопросу - что такое ФП )))
[9:23:38 PM] Anton Chikin:
бляяя
[9:23:41 PM] Андрей Иванов:
напишите, какие языки по вашему ФЯ
edited
[9:23:51 PM] Anton Chikin:
никакие
Андрей Иванов removed Anton Chikin
[9:24:11 PM] ilya korotkov:
я только хаскелем баловался и sicp почитывал
эрланг вот на слуху куда не плюнь)
[9:24:55 PM] Андрей Иванов:
вот и яхочу сказать, что если не брать чистый и бескомпромиссный хаскель, то остальные - с оговорками )
что считать критерием функциональности?
мне нравится критерий - наличие функций как объектов первого класса языка
[9:25:36 PM] ilya korotkov:
имхо отсутствие side эффектов
[9:25:53 PM] Андрей Иванов:
но тогда с недавних пор почти во все языки завезли лямбды - даже в С++
[9:26:21 PM] Igor Lyskov:
в двух словах, что такое side-эффекты?
[9:26:34 PM] Андрей Иванов:
это называют мультипарадигменность. и ровно в той мере, в какой язык позволяет писать чистое ФП, он ФЯ
[9:26:56 PM] ilya korotkov:
ну вот глобальные переменные самый лютый пример сайд эффекта
[9:26:58 PM] Андрей Иванов:
сайд/эффекты - это интересный вопрос ) в двух словах не выйдет
[9:27:29 PM] ilya korotkov:
меняются из разных функций и при вызове следующей черт знает чему равна эта переменная, если используется многопоточность то совсем печалька
[9:27:41 PM] Андрей Иванов:
и то же глобальное состояние прекрасно эмулируется в хаскеле - а он чистый. ка так?
[9:27:53 PM] ilya korotkov:
я не знаю) я не шарю)
[9:28:10 PM] Igor Lyskov:
все зависит от того, как использовать
[9:28:25 PM] Андрей Иванов:
если мы будем ВОСПРИНИМАТЬ глобальное состояние как внешнее по отношению к программе явление - то его изменение это сайд эффект
но в том же хаскеле есть стейт -монада. пишется руками даже без знания о том что такое монады
щас поясню
любая функция, вычисляемая внутри этой монады
принимает на вход не только свои аргументы
Anton Chikin joined group via invite link
[9:29:46 PM] Андрей Иванов:
а еще и состояние
и возвращает не только свой результат
а еще и новое состояние
если она не меняет состояние - то просто транзитом через себя возвращает входное
если меняет - возвращает измененное, и следующие функции примут на свой вход уже это измененное
[9:30:58 PM] Igor Lyskov:
как по английски монада?
[9:31:17 PM] Андрей Иванов:
вот такая семантика позволяет эмулировать изменяемое состояние в чистом языкен
ладно, вернемся ближе к нашему боту )
+ 1 2
[9:32:23 PM] Liscript-bot:
3
[9:32:38 PM] Андрей Иванов:
по поводу разных порядков редукции, чистоты и прочего
как я уже говорил, у меня совсем не чистый ФЯ
например
def a 1
[9:32:58 PM] Liscript-bot:
OK
[9:33:00 PM] Андрей Иванов:
a
[9:33:00 PM] Liscript-bot:
1
[9:33:20 PM] Андрей Иванов:
что будет при def a (+ a 1) - как думаете?
понятно, я сам с собой говорю )
[9:33:51 PM] ilya korotkov:
ну а = 2
[9:33:51 PM] Anton Chikin:
2
[9:33:56 PM] Андрей Иванов:
проверим
def a (+ a 1)
[9:34:02 PM] Liscript-bot:
OK
[9:34:04 PM] Андрей Иванов:
a
[9:34:04 PM] Liscript-bot:
2
[9:34:17 PM] Андрей Иванов:
правильно ) это семантика моего вычисленгия
как в паскале
но в F# было бы совсем не то
[9:34:56 PM] Igor Lyskov:
я в телефоне, но весь во внимании
[9:35:00 PM] Андрей Иванов:
там скорее всего зациклилось бы
в хаскеле - ничего страшного бы не произошло до момента обращения к а - это ленивый язык
но при попытке напечатать а было бы зацикоивание
в схеме не знаю как, но что мог бы сделать я в своем языке?
например, запрещать переопределять переменные если они уже есть
и мало чего бы поменялось - поверьте )
большинство рекурсивных алгоритмов не нуждаются в этом
на не надо перезаписывать переменную почти никогда
но я сделал такую семантику, и ушел еще дальше от чистого ФП
теперь еще пример
a
[9:38:11 PM] Liscript-bot:
2
[9:38:49 PM] Андрей Иванов:
defn f (x)
(def a (+ a 1))
(+ x a)
[9:38:49 PM] Liscript-bot:
OK
[9:39:08 PM] Андрей Иванов:
что вернет f 1 икакое будет а ?
[9:39:23 PM] Danila Litvinov:
2, 3
[9:39:35 PM] Андрей Иванов:
еще мнения?
[9:39:43 PM] ilya korotkov:
4
[9:39:50 PM] Danila Litvinov:
3, 3
[9:40:17 PM] ilya korotkov:
я возможно не въезжаю, но почему 2 значения то?)
[9:40:19 PM] Андрей Иванов:
вооот, мнения расхлодятся. а почему? потому что эти вопросы уже из области дизайна языка
можно сделать так, а можно по-другому. и то и другое будет отклонение от чистого ФП - но что выберем при создании языка, то и получим
проверим
f 1
[9:41:03 PM] Liscript-bot:
4
[9:41:08 PM] Андрей Иванов:
ф
a
[9:41:11 PM] Liscript-bot:
2
[9:41:26 PM] Андрей Иванов:
у кого есть идеи почему 4 и 2?
[9:41:39 PM] Anton Chikin:
из-за скоупа
[9:41:39 PM] ilya korotkov:
мне вот не понятно почему а двум остался равен
[9:41:50 PM] Андрей Иванов:
правильна - из-за скоупа
щас все объясню )
[9:41:57 PM] Anton Chikin:
потому что а был переопределен только внутри f
[9:42:17 PM] Андрей Иванов:
именно. внутри f jghtltkztncz cdjq ckjdfhm gthtvtyys[
определяется свой словарь переменных
и когда я завожу новую переменную внутри функции - она ее локальная. как в паскале, хаскеле и вообще везде
но до того как она заведена, я рассчитываю значение, которое ей присвою. это терм (+ 1 а). внутренней переменной еще нет - он берет из глобального скоупа
ва глобальном скоупе а = 2
итого, внутренняя переменная а равна 3. а с глобальной ничего не произошло
функция возвращает 4, глобальная а остается равной 2
резюме - из внутреннего скоупа функции мы так запросто не можем менять переменные внешнего окружения
в этом есть смысл. наша функция не портит ничего что снаружи нее
и это по-фП шному
любой рекурсивный вызов функций имеет дело с теми же именами переменных
и если они не будут создаваться новые при каждом вхождении, то фиг вам , а не стек вызоваов с разгными аргументами
но и тут есть способ все поломать ) в схеме, лискрипте и ит.п.
Что будет при
defn f (x)
(set! a (+ a 1))
(+ x a)
?
[9:48:23 PM] ilya korotkov:
set! что за шляпа?
[9:48:24 PM] Liscript-bot:
OK
[9:48:52 PM] Андрей Иванов:
ну по аналогии можно догадаться - это страшный мутирующий оператор присваивания
defn f (x)
(set! a (+ a 1))
(+ x a)
[9:49:06 PM] Liscript-bot:
OK
[9:49:51 PM] Андрей Иванов:
в F# он есть, в схеме, еще много где. Причем, язык и без него справляется в большинстьве случаев, но вот ввели
[9:49:51 PM] ilya korotkov:
хрен знает) я не понимаю что будет set! a (+ a 1)
[9:50:01 PM] Андрей Иванов:
f 1
[9:50:02 PM] Liscript-bot:
4
[9:50:04 PM] Андрей Иванов:
a
[9:50:04 PM] Liscript-bot:
3
[9:50:41 PM] Андрей Иванов:
set! не создает новую локальную переменную, а меняет ближайшую внешнюю с этим именем
[9:50:41 PM] Liscript-bot:
OK
[9:50:48 PM] Андрей Иванов:
не
++ не
[9:50:57 PM] Liscript-bot:
не
[9:51:26 PM] Андрей Иванов:
это я вам показываю явные моменты где чистое ФП, а где отклонения
[9:51:36 PM] ilya korotkov:
ну тогда то же самое что и в предыдущем примере только глобальная а уже будет равна 3
[9:51:53 PM] Андрей Иванов:
правильно - см результаты вызова выше
a
[9:52:00 PM] Liscript-bot:
3
[9:52:33 PM] Андрей Иванов:
теперь про аппликативную и нормальную редукционные стратегии поговорим )
кто знает какие ЯП?
[9:53:17 PM] ilya korotkov:
функциональные никакие, только основы синтаксиса хаскеля и схемы
[9:53:28 PM] Андрей Иванов:
я вообще про любые сейчас
[9:53:39 PM] ilya korotkov:
с++ питон баш
[9:54:11 PM] Igor Lyskov:
C,pas,asm
[9:54:11 PM] Андрей Иванов:
короче, вопрос - есть функция 2 аргументов. В ваших языках определен строгий порядок их вычисления перед вызовом функции?
понятен вопрос?
[9:54:35 PM] ilya korotkov:
в плюсах нет
в других особо не задумывался
[9:55:20 PM] Андрей Иванов:
потому что значения аргументов вызова сами могут рассчитываться через свои функеции, меняющие глобальныей стейт и порядок расчета аргументов тогда определяет их значения
это важный момент в колл-конвенциях языка
в Схеме порядок не определен. в джаве - строго слева направо
в хаскеле - неважен, потому что чистое ФП и пофигу )
хоть параллельно на 2 процессорах
у меня здесь строго слева направо
пример
[9:57:15 PM] ilya korotkov:
наверно стоит сказать про sequence point
[9:57:42 PM] Андрей Иванов:
defn f (x) (print "x = " x /n) x
[9:57:42 PM] Liscript-bot:
OK
[9:57:46 PM] Андрей Иванов:
f 1
[9:57:46 PM] Liscript-bot:
x = 1/n1
[9:57:58 PM] Андрей Иванов:
defn f (x) (print "x = " x \n) x
[9:57:59 PM] Liscript-bot:
OK
[9:58:01 PM] Андрей Иванов:
f 1
[9:58:01 PM] Liscript-bot:
x = 1
1
[9:58:13 PM] Igor Lyskov:
\n
[9:58:19 PM] Андрей Иванов:
defn g (a b) + a b
[9:58:19 PM] Liscript-bot:
OK
[9:58:29 PM] Андрей Иванов:
g (f 1) (f 2)
[9:58:30 PM] Liscript-bot:
x = 1
x = 2
3
[9:58:58 PM] Андрей Иванов:
сначала первый аргумент, потом второй. если порядок строго определен - этим можно пользоваться
но это даже главное, что хотел показать
а хотел показать нормальную/аппликативную редукцию
вот есть функция
defn g (x) + x x
[9:59:41 PM] Liscript-bot:
OK
[9:59:51 PM] Anton Chikin:
А такой вопрос - почему f чистая функция если результат Ее вычисления зависит от внешней переменной а?
[10:00:04 PM] Андрей Иванов:
щас, доскажу и вопрос потом
[10:00:17 PM] ilya korotkov:
+1 вопросу
[10:00:18 PM] Андрей Иванов:
что будет при вызове g (f 1) ?
я отвечу потом на ваш вопрос, сначала закончим с порядком вызовов
т\ак что скажете?
[10:01:14 PM] ilya korotkov:
эм... а чему n равен
[10:01:23 PM] Андрей Иванов:
f
[10:01:24 PM] Liscript-bot:
(lambda (x) ((print "x = " x \n) x))
[10:01:27 PM] Андрей Иванов:
g
[10:01:27 PM] Liscript-bot:
(lambda (x) (+ x x))
[10:01:33 PM] Anton Chikin:
2
[10:01:35 PM] Андрей Иванов:
что будет при g (f 1)
[10:01:52 PM] ilya korotkov:
аа эт окончание строки
[10:01:52 PM] Андрей Иванов:
интересует весь вывод
результат то понятно что 2
что будет напринтовано
[10:02:48 PM] ilya korotkov:
вроде ж x=1
[10:03:03 PM] Андрей Иванов:
бот что напечатает в окне - полностью
[10:03:21 PM] Igor Lyskov:
x= 1 \n 2
[10:03:29 PM] Андрей Иванов:
правильно
проверяем
g (f 1)
[10:03:38 PM] Liscript-bot:
x = 1
2
[10:04:05 PM] Андрей Иванов:
сначала вычислился единственный аргумент g , при вычислении наприновал, и вернулся результат
этта назывется строгий вызов по значению
в терминях лямбда-исчисления - аппликативный порядок редукции - сначала внутренние аргументы вычисляются, а потом к ним применяетсмя фунгкция
теперь еще пример
defmacro h (x) + x x
[10:05:12 PM] Liscript-bot:
OK
[10:05:25 PM] Андрей Иванов:
что вернет h (f 1) ?
h - 'nj vfrhjc
[10:05:45 PM] Liscript-bot:
Андрей: не связанная переменная: nj
[10:05:54 PM] Андрей Иванов:
это макрос
h
[10:05:59 PM] Liscript-bot:
(macro (x) (+ x x))
[10:06:05 PM] ilya korotkov:
x =1 \n x=2 \n 3
[10:06:19 PM] Андрей Иванов:
еще идеи?
ладно, проверяем
h (f 1)
а бот заснул )
[10:07:56 PM] ilya korotkov:
))
[10:08:08 PM] Андрей Иванов:
defn f (x) (print "x = " x \n) x
[10:08:08 PM] Liscript-bot:
OK
[10:08:11 PM] Андрей Иванов:
f 1
[10:08:11 PM] Liscript-bot:
x = 1
1
[10:08:25 PM] Андрей Иванов:
defmacrj h (x) + x x
defmacro h (x) + x x
[10:08:36 PM] Liscript-bot:
OK
[10:08:40 PM] Андрей Иванов:
h (f 1)
[10:08:40 PM] Liscript-bot:
x = 1
x = 1
2
[10:08:55 PM] Андрей Иванов:
то есть это честный макрос
он не вычисляет свои аргументы, заменяет в своем теле все вхождения x на невычисленные аргументы и вычисляет полученную форму
то есть в результате раскрытия макроса мы получаем + (f 1) (f 1)
и честно вычисляем этот терм - печатается 2 раза
это называется нормальный порядок редукции - НЕ ВЫЧИСЛЯЯ внутренни термы раскрывать внешний
или ленивая стратегия вычислений
[10:11:10 PM] ilya korotkov:
как сишный макрос типо того?
[10:11:12 PM] Андрей Иванов:
в хаскеле именно такая
ну да, поэтому и название такое
только у меня макрос, как и функция - полноценный объект рантайма языка - можно создавать во время исполнения, помещать с списки и т.п.
но это уже детали. на примере моих функций и макросов я хотел показать различие редукционных стратегий
[10:12:32 PM] ilya korotkov:
ну типо синтаксический макрос которые все хотят видеть в плюсах, но которых не будет никогда)
[10:12:52 PM] Андрей Иванов:
таких макросов даже в лиспе нет )
[10:13:08 PM] ilya korotkov:
а в лискрипте есть?)
[10:13:14 PM] Андрей Иванов:
ага )
рантаймовые макросы - такой вот оксюморон.
[10:13:36 PM] ilya korotkov:
а в лиспе тогда какие?
[10:13:49 PM] Андрей Иванов:
у меня нет фазы раскрытия макросов перед исполнением кода
[10:13:56 PM] Anton Chikin:
Reader я подозреваю
edited
[10:14:34 PM] Андрей Иванов:
что Ридер? я про сто, что у меня макросы - рантайм объекты 1 класса
[10:15:00 PM] Anton Chikin:
Ридер макрос в лиспе
[10:15:53 PM] Андрей Иванов:
но это удже деталь реализации. наверное, я не знаю лисп. Но знаю что большинство макросов уходят на стади макрораскрытия перед компиляцией и в рантайме вроде ихзх не создать
[10:16:25 PM] Anton Chikin:
Да
[10:16:25 PM] Андрей Иванов:
ладно, был вопрос - какое право имеет чистая функция читать а из глобального контекста )
у меня встречный вопрос - а как это нарушает понятие чистоты и даже семантику лямбда исчисления?
[10:17:15 PM] ilya korotkov:
ну чистая функция по определению без сайд эффектов же
либо я не шарю
[10:17:27 PM] Андрей Иванов:
если потребовать, чтобы эта "переменная" была константа и никогда не менялась в своем стекйте?
и где здесь сайд-эффект?
есть константа Пи
[10:17:51 PM] ilya korotkov:
хм, ну тогда нету, да
[10:17:52 PM] Андрей Иванов:
определена в глобальном стейте
в чем криминал из чистых функция читать Пи?
[10:18:14 PM] ilya korotkov:
ни в чем
[10:18:21 PM] Андрей Иванов:
вот менять Пи нельзя )
[10:18:28 PM] ilya korotkov:
но констант явно не достаточно для нормальной жизни )
[10:18:47 PM] Андрей Иванов:
оставь эти стереотипы
в хаскеле все константы
[10:19:12 PM] ilya korotkov:
вот поэтому я и не понимаю как на нем пишут что-то большое))
[10:19:46 PM] Андрей Иванов:
тащат стейт (закадрово через сахар) через все функции
[10:19:59 PM] ilya korotkov:
в общем жара
[10:20:04 PM] Андрей Иванов:
там единственный способ что-то изменить - протащить это через функцию
к этому быстро привыкаешь ) я как-то на чистом Си написал код, решающий головоломку Хитори (типу Судоку), где ВСЕ переменные у меня были const
когда возникает соблазн менять значение переменных?
когда стереотипы внешней памяти, где они лежать, и которая доступна для изменения из любого места
вот и получается, что сейчас а=1, а через операцию уже а=2
в одном и том же контексте
и поэтому циклы - все крутят и ждут, когда же наша а не станет равной 0
в одном и том же скоупе
а рекурсивные функции при вызове создают новый скоуп - и там константа с тем же именем а может иметь другое значение
и вместо переетирания в одном скоупе создается стек вызовов/скоупов, в каждом из ктороых ничего не перетирается
но ладно, в Лискрипте можно и так и сяк )
есть кто живой? )
[10:25:32 PM] Danila Litvinov:
+
[10:25:36 PM] Андрей Иванов:
id
[10:25:37 PM] Liscript-bot:
(lambda (x) x)
[10:25:42 PM] ilya korotkov:
так в цикле ж тоже можно каждый раз создавать переменные локальные
[10:25:56 PM] Андрей Иванов:
каждый раз создавать - нет
паотому что понятие цикла - это ОДИН СКОУП
и в нем приходится только менять )
[10:26:22 PM] ilya korotkov:
for(int i=0; i<5; ++i) { int a = 1; }
или ты о другом чуток
[10:26:46 PM] Андрей Иванов:
у тебя тело цикло созлдает свой отдельны йскоуп
но он все равно ОДИН на все итерации цикла
и в нем и меняется счектчик
смотри
def n 5
[10:27:30 PM] Liscript-bot:
OK
[10:28:33 PM] Андрей Иванов:
defmacro t () (ppint "n = " n \n) (set! n (- n 1)) (t)
[10:28:33 PM] Liscript-bot:
OK
[10:28:37 PM] Андрей Иванов:
(t)
t
[10:28:41 PM] Liscript-bot:
Андрей: идет вычисление...
[10:28:45 PM] Андрей Иванов:
!
[10:28:45 PM] Liscript-bot:
Андрей: вычисление прервано
[10:28:54 PM] Андрей Иванов:
)) yt ghjrfnbkj yfdcrblre )
defmacro t () (ppint "n = " n \n) (set! n (- n 1)) (cond (> n 0 ) (t) "End")
[10:29:37 PM] Liscript-bot:
OK
[10:29:39 PM] Андрей Иванов:
(t)
[10:29:40 PM] Liscript-bot:
End
[10:30:03 PM] Андрей Иванов:
defmacro t () (print "n = " n \n) (set! n (- n 1)) (cond (> n 0 ) (t) "End")
[10:30:03 PM] Liscript-bot:
OK
[10:30:07 PM] Андрей Иванов:
(t)
[10:30:07 PM] Liscript-bot:
n = -7607300
End
[10:30:15 PM] Андрей Иванов:
n
[10:30:16 PM] Liscript-bot:
-7607301
[10:30:21 PM] Андрей Иванов:
def n 5
[10:30:22 PM] Liscript-bot:
OK
[10:30:24 PM] Андрей Иванов:
(t)
[10:30:25 PM] Liscript-bot:
n = 5
n = 4
n = 3
n = 2
n = 1
End
[10:30:31 PM] Андрей Иванов:
вооооот
вот вам полдный аналог императивного цикла - никаких новых скоупов, все происхордит в глобальном
пример понятен?
[10:31:14 PM] ilya korotkov:
не погодь
[10:31:15 PM] Андрей Иванов:
n
[10:31:16 PM] Liscript-bot:
0
[10:31:23 PM] Андрей Иванов:
def n 10
[10:31:24 PM] Liscript-bot:
OK
[10:31:26 PM] Андрей Иванов:
(t)
[10:31:26 PM] Liscript-bot:
n = 10
n = 9
n = 8
n = 7
n = 6
n = 5
n = 4
n = 3
n = 2
n = 1
End
[10:31:29 PM] Андрей Иванов:
n
[10:31:29 PM] Liscript-bot:
0
[10:31:59 PM] Андрей Иванов:
defmacro t () (print "n = " n \n) (set! n (- n 1)) (cond (> n 0 ) (t) "End")
[10:32:00 PM] Liscript-bot:
OK
[10:32:07 PM] ilya korotkov:
мда, я могу сказать, что мне надо заново читать сицп))
я лично так не могу въехать быстро
[10:32:39 PM] Андрей Иванов:
я объясню. В СИКПе этого нет ) Там макросы не освещены
[10:32:54 PM] ilya korotkov:
эх
[10:33:14 PM] Андрей Иванов:
у меня макрос - а он не создает никакой новый скоуп а вычисляется в текущем скоупе вызова - в нашем случае глобальном
при вычислении он принтует глобальную переменную, уменьшает ее на 1, и по суловию пока она > 0 вызывает сам себя - и повторяет то же самое
то есть это - императивный цикл с деструктивным изменением счетчика в одном и том же скоупе
для этого нам необходимо деструктивное присваивание - изменение значения
кто может (если етсчь кто живой) написать тот же вывод но в чистом ФП стиле?
[10:36:05 PM] ilya korotkov:
))
не, вряд ли кто сможет так сходов)
[10:36:29 PM] Igor Lyskov:
Я в пути :)
[10:36:43 PM] Андрей Иванов:
ключевое слово - рекурсия
сммотрите
defn r (n) cond (> n 0) ((print "n = " n \n) (r (- n 1))) "End"
[10:37:59 PM] Liscript-bot:
OK
[10:38:03 PM] Андрей Иванов:
r 5
[10:38:03 PM] Liscript-bot:
n = 5
n = 4
n = 3
n = 2
n = 1
End
[10:38:26 PM] Андрей Иванов:
что здесь чистое а что не чистое )
принт - нечистый. в хаскеле бы не прокатило. нелдьзя песатать посреди редукции
только набирать строковый результат и возвращать в самом конце
но а все остальное - чистое
никаких деструктивных присваиваний
[10:39:54 PM] ilya korotkov:
слушай, а если n < 0 ?
[10:39:57 PM] Андрей Иванов:
между прочим, в любом С эта функция будет написана точно так же
а мы прерываем цепочку рекурсивныфх вызовов когда n = 0
defn r (n) cond (> n 0) ((print "n = " n \n) (r (- n 1))) "End"
[10:40:42 PM] Liscript-bot:
OK
[10:41:40 PM] Андрей Иванов:
На самом деле циклы не являются необходимыми в языке
рекурсия гораздо шире их по возможностям
[10:42:09 PM] ilya korotkov:
ну это известный факт)
вот только мозг начинает давать сбой без циклов))
[10:42:39 PM] Андрей Иванов:
а раз есть что-то более мощное, то нет смысла в наличии циклов
наверное опрометчиво будет спрашивать, сможет ли кто написать функцию с тем же выводом но без принтов посреди вычислений - то етсь полностью чистую? )
[10:43:54 PM] ilya korotkov:
))
хм, ну тупо убрать принт и все
[10:44:35 PM] Андрей Иванов:
убираем принт
defn r (n) cond (> n 0) (r (- n 1)) "End"
[10:45:01 PM] ilya korotkov:
defn r (n) cond (> n 0) ( (r (- n 1))) "End"
[10:45:13 PM] Liscript-bot:
OK
OK
[10:45:21 PM] Андрей Иванов:
r 5
[10:45:21 PM] Liscript-bot:
End
[10:45:29 PM] ilya korotkov:
)
[10:45:31 PM] Андрей Иванов:
и это предсказуемо )
надо чтобы печатал все энки
defn r (n) cond (> n 0) (++ "n = " n \n (r (- n 1))) "End"
[10:46:38 PM] Liscript-bot:
OK
[10:46:44 PM] Андрей Иванов:
f 5
r 5
[10:46:49 PM] Liscript-bot:
n = 5
n = 4
n = 3
n = 2
n = 1
End
[10:47:09 PM] ilya korotkov:
жара
[10:47:21 PM] Андрей Иванов:
вот вариант из чистого ФП - никаких циклов, никакого изменяемого состояния, никаких побочных эффектов
вся выведенная ботом строка - это одна строка результата функции
а внутри функции мы только накапливает\м ее конкатенацией
то есть по сути я сейчас написал 3 варианта функции с одним и тем же выводом - кондовый императивный на цикле и изменяемой переменной, рекурсивный с прином и чистый ФП-шный
вот так примерно люди и пишут на Си, F# или Haskell :)
[10:49:58 PM] ilya korotkov:
эмм, а сам принт то чем отличается от простого "x = " x ?
[10:50:33 PM] Андрей Иванов:
принт принтует тут же в выходной поток. А простое - ничего не делает
[10:50:53 PM] ilya korotkov:
а типо все в конце печатается при простом?
а не на каждом цикле рекурсии
[10:51:23 PM] Андрей Иванов:
именно. я же писал. Это сам РЕПЛ печатает результа всей функции после ее вычисления
именно
[10:52:40 PM] ilya korotkov:
не, ну это трудно)
я поэтому и плюнул на хаскель когда дошел до монад))
[10:53:34 PM] Андрей Иванов:
ладно, обязательная программа доклада наверное все, теперь просто в свободном режиме продолжим )
[10:53:46 PM] ilya korotkov:
типа вопросы?)
[10:54:10 PM] Андрей Иванов:
ну только не уровня "а почему нет монад в Си" )
[10:54:16 PM] ilya korotkov:
та нее
я вот знаешь что хотел спросить
раз уж дело зашло о фп
вот если посмотреть доклады на конференции highload
то там часто фигурирует эрланг
вот в чем профит этой самой модели акторов?
почему ее использует в движке хрома например
[10:55:50 PM] Андрей Иванов:
высокая надежность и отказоустойчивостиь. У тебя микросервисная архитектура считай из коробки.
[10:56:08 PM] ilya korotkov:
я конечно не владею матчастью
[10:56:19 PM] Андрей Иванов:
но скорость конечно уступает С++. Поэтому везде компромиссы.
[10:56:22 PM] ilya korotkov:
но почему раньше тогда ее не применяли?
[10:57:27 PM] Андрей Иванов:
про хром, эрланг и прочие интересные вещи я не могу рассказать )
[10:57:43 PM] ilya korotkov:
печаль)
ну это так
просто философия
[10:58:22 PM] Андрей Иванов:
пойду проверю другие форумы
[10:58:35 PM] ilya korotkov:
мне вот интересно у твоего бота то что внутри?
что есть этот самый рэпл?
[10:59:55 PM] Андрей Иванов:
давай если соберутся хотя бы несколько человек кому это интересно, я детальнее расскажу, ок?
[11:00:09 PM] ilya korotkov:
ок...
но походу всем плевать))
я думал будет еще кто-то
[11:01:08 PM] Андрей Иванов:
значит будет по Маяковскому - если на небе не зажигаются звезды - значит это никому не нужно :) Но надо принимать реальность какова она есть. без звезд ))))
[11:01:42 PM] ilya korotkov:
ну возможно, однако прикол в том, что ты побудил меня заново читать sicp
и с монадами разобраться
[11:02:29 PM] Андрей Иванов:
это хорошо. удачи в разборе )
[11:02:45 PM] ilya korotkov:
спасибо тебе, милый человек, за все
жаль что правда все так кончилось
вечер пятницы походу не лучшее время)
[11:14:35 PM] Danila Litvinov:
я, к сожалению, не могу всё время присутствовать. Но мне интересно и я надеялся почитать всё завтра сутра.
[11:15:58 PM] Андрей Иванов:
если доступна история сообщений, то да
[11:17:26 PM] Danila Litvinov:
ну я ненадолго отходил, не больше чем полчаса
[11:18:07 PM] ilya korotkov:
> Danila Litvinov
> ну я ненадолго отходил, не больше чем полчаса
а ты sicp читал?
[11:19:21 PM] Danila Litvinov:
нет
[11:19:49 PM] ilya korotkov:
без нее по-моему вообще нереально понять так с ходов)
[11:20:50 PM] Danila Litvinov:
я читал что-то то CLIPS, так что более-менее понимаю
тут, прежде всего, нужна практика
на самом деле, это в свое время открыло мне глаза и очень помогло в написании большого проекта
[11:22:40 PM] ilya korotkov:
а че за проект?
[11:22:45 PM] Danila Litvinov:
с работой связано
примитивно можно назвать конвертером
всё было построено на функциональном подходе, был набор обработчиков, каждый был независим друг от друга. Они получали данные и отдавали. Обработчики запускались при возникновении определенного события
[11:24:19 PM] ilya korotkov:
типа паттерн reactor?
[11:25:22 PM] Danila Litvinov:
что-то похожее на то, но не в чистом виде
[11:26:06 PM] ilya korotkov:
я вот почему стал фп чуток интересоваться - хотелось сортировку сделать в компайл-тайме
just for fun
рекурсивно
смотрел книгу по хаскелю - там как раз сортировка была как пример программы
ну и так пошло поехало
смешно, но факт)
[11:28:57 PM] Danila Litvinov:
тут может быть проблема с глубиной рекурсии
[11:29:41 PM] ilya korotkov:
ну я на шаблонах в плюсах хотел накостылять) там глубина рекурсии устанавливается
Metadata
Metadata
Assignees
Labels
No labels