Forwarded from #corpix
Через 3 месяца будет год как я начал изучать racket и вообще погружаться в мир лиспов с целью разобраться и начать использовать всю их мощь для своих собственных проектов.
До этого я в основном программировал на Go, а на жизнь зарабатывал тем что программировал на js под nodejs и браузеры, а также делал всякую инфраструктуру для разработчиков в одной конторе, которая занимается поиском.
Кто и что привело меня в лиспы?
История не короткая, но я постараюсь. Прошлым летом я делал сервисы для сбора и анализа данных о криптовалюте с бирж. Всё это делалось на Go и мне нравилось всё кроме скорости с которой я двигался и уровня абстракции, который способна предоставить гошная система типов(иными словами: "писанины много"). Маленькая скорость разработки была вызвана желанием абстрагироваться от конкретики, собирая сервисы из компонентов как из конструктора, что довольно не просто делать в Go.
Эти сервисы делались для десктопного приложения-информера по крипте, который писал другой человек на ClojureScript и в какой-то момент я решил посмотреть "чё там в кложуре есть".
До этого у меня было несколько набегов на мирок JVM, но не вдаваясь в детали, очень мягко скажу про весь java мир - не зашло, но того что я увидел в процессе копания в кложуре хватило чтобы понять: в университете я уделял слижком мало времени лиспу. И я начал искать альтернативы, постепенно придя к racket и начав погружаться в SICP(которую я всё ещё разбираю кстати).
Тут наверное стоит заметить, что я не искал супер быстрый язык для реализации своих идей на практике, я вообще считаю что выбирать язык по критерию "быстрый, а остальное не так важно" далеко не всегда правильно. Так что я искал выразительный язык, программы на котором можно легко менять в процессе разработки.
Стал ли я счастливее после этого?
Определённо да, хоть я и понимаю что racket далеко не идеален, например:
- пакетный менеджер говно(а вы думаете, почему мне удобнее монорепа - пользуюсь пакетным менеджером по минимуму)
- документации много, но местами она не содержит примеров и написана сухим академическим языком(теория без практики)
- некоторые части довольно лохматы или вовсе не понятны
- некоторые библиотеки из стандартного набора ужасны(а вы думаете, зачем мне свой велосипед в виде HTTP клиента?)
- ошибки рантайма иногда ставят в ступор, например когда пишешь свои макросы, но в большинстве случаев довольно информативны
- прямо скажем, готовых модулей могло бы быть и побольше
Ещё хочу добавить что литературы не так много, а та что есть, например:
- https://beautifulracket.com/
- http://www.realmofracket.com/
Учит на странных примерах(первая), либо старовата и не содержит некоторых фич(вторая).
Но даже не смотря на все эти изъяны я давно не получал столько удовольствия от программирования, например:
За последние 2 дня полностью перелопатил написанный несколько месяцев назад клиент к NSQ, внеся:
- поддержку отложенной финализации и возврата сообщений
(это когда очередь может подождать пока я наберу батч для сохранения в базу, а если я вдруг упаду то пришлёт мне или другому сервису теже сообщения после указанного таймаута)
- конфигурируемые statsd метрики и логирование
- покрыл это всё тестами
На Go у меня похожая задача заняла бы недели. На js меньше, но моё психологическое здоровье под угрозой.
Или вот ещё:
https://xn--r1a.website/documentsjournal/463
Обёртка была написана за вечер, а высокоуровневая часть тоже не заставила себя ждать(и это была моя первая FFI обертка на этом языке, так что я ещё документацию курил).
Окей, что дальше?
Продолжаю использовать racket в своих собственных проектах. Но я не буду ограничиваться лишь им одним, сейчас я дочитываю книгу Common Lisp: A Gentle Introduction to Symbolic Computation и перехожу к Practical Common Lisp.
Ещё я скорее всего попробую chicken scheme, поскольку каждый раз когда я нахожу недочет в racket то иду проверять его наличие в chicken и чаще не нахожу.
Возможно один из них(CL или chicken) заменит в моём арсенале racket, а может они будут сосуществовать в гармонии, посмотрим.
До этого я в основном программировал на Go, а на жизнь зарабатывал тем что программировал на js под nodejs и браузеры, а также делал всякую инфраструктуру для разработчиков в одной конторе, которая занимается поиском.
Кто и что привело меня в лиспы?
История не короткая, но я постараюсь. Прошлым летом я делал сервисы для сбора и анализа данных о криптовалюте с бирж. Всё это делалось на Go и мне нравилось всё кроме скорости с которой я двигался и уровня абстракции, который способна предоставить гошная система типов(иными словами: "писанины много"). Маленькая скорость разработки была вызвана желанием абстрагироваться от конкретики, собирая сервисы из компонентов как из конструктора, что довольно не просто делать в Go.
Эти сервисы делались для десктопного приложения-информера по крипте, который писал другой человек на ClojureScript и в какой-то момент я решил посмотреть "чё там в кложуре есть".
До этого у меня было несколько набегов на мирок JVM, но не вдаваясь в детали, очень мягко скажу про весь java мир - не зашло, но того что я увидел в процессе копания в кложуре хватило чтобы понять: в университете я уделял слижком мало времени лиспу. И я начал искать альтернативы, постепенно придя к racket и начав погружаться в SICP(которую я всё ещё разбираю кстати).
Тут наверное стоит заметить, что я не искал супер быстрый язык для реализации своих идей на практике, я вообще считаю что выбирать язык по критерию "быстрый, а остальное не так важно" далеко не всегда правильно. Так что я искал выразительный язык, программы на котором можно легко менять в процессе разработки.
Стал ли я счастливее после этого?
Определённо да, хоть я и понимаю что racket далеко не идеален, например:
- пакетный менеджер говно(а вы думаете, почему мне удобнее монорепа - пользуюсь пакетным менеджером по минимуму)
- документации много, но местами она не содержит примеров и написана сухим академическим языком(теория без практики)
- некоторые части довольно лохматы или вовсе не понятны
- некоторые библиотеки из стандартного набора ужасны(а вы думаете, зачем мне свой велосипед в виде HTTP клиента?)
- ошибки рантайма иногда ставят в ступор, например когда пишешь свои макросы, но в большинстве случаев довольно информативны
- прямо скажем, готовых модулей могло бы быть и побольше
Ещё хочу добавить что литературы не так много, а та что есть, например:
- https://beautifulracket.com/
- http://www.realmofracket.com/
Учит на странных примерах(первая), либо старовата и не содержит некоторых фич(вторая).
Но даже не смотря на все эти изъяны я давно не получал столько удовольствия от программирования, например:
За последние 2 дня полностью перелопатил написанный несколько месяцев назад клиент к NSQ, внеся:
- поддержку отложенной финализации и возврата сообщений
(это когда очередь может подождать пока я наберу батч для сохранения в базу, а если я вдруг упаду то пришлёт мне или другому сервису теже сообщения после указанного таймаута)
- конфигурируемые statsd метрики и логирование
- покрыл это всё тестами
На Go у меня похожая задача заняла бы недели. На js меньше, но моё психологическое здоровье под угрозой.
Или вот ещё:
https://xn--r1a.website/documentsjournal/463
Обёртка была написана за вечер, а высокоуровневая часть тоже не заставила себя ждать(и это была моя первая FFI обертка на этом языке, так что я ещё документацию курил).
Окей, что дальше?
Продолжаю использовать racket в своих собственных проектах. Но я не буду ограничиваться лишь им одним, сейчас я дочитываю книгу Common Lisp: A Gentle Introduction to Symbolic Computation и перехожу к Practical Common Lisp.
Ещё я скорее всего попробую chicken scheme, поскольку каждый раз когда я нахожу недочет в racket то иду проверять его наличие в chicken и чаще не нахожу.
Возможно один из них(CL или chicken) заменит в моём арсенале racket, а может они будут сосуществовать в гармонии, посмотрим.
Forwarded from dd if=/dev/stuff of=/dev/tg
Реализовал сегодня на работе Tagless Final на TypeScript для работы с браузерным стораджем. А потом выкинул нахуй. Расскажу немного о контексте такого решения.
Сейчас на работе я пишу SDK, с помощью которого будут писать переиспользуемые модули — блоки бизнес-функциональности, которые можно подключать к любому (в теории) приложению как некие черные ящики, тем самым экономя бизнесу деньги на повторную разработку. В рамках этого SDK нужно реализовать слой персистенса, абстрагирующегося от некоего хранилища. Это может быть session storage, local storage, IndexedDB, WebSQL или вообще персист на сервер через REST. Я спроектировал это так, что модуль получает на вход абстрактную алгебру
Но есть нюанс. В рамках продвигаемой архитектуры приложений я требую, чтобы все работы с хранилищем и сетевыми запросами происходили в рамках
Мораль: нельзя позволять себе терять виденье общей картины, углубляясь в столь приятные (но порой ненужные) технические детали.
Такие дела.
Сейчас на работе я пишу SDK, с помощью которого будут писать переиспользуемые модули — блоки бизнес-функциональности, которые можно подключать к любому (в теории) приложению как некие черные ящики, тем самым экономя бизнесу деньги на повторную разработку. В рамках этого SDK нужно реализовать слой персистенса, абстрагирующегося от некоего хранилища. Это может быть session storage, local storage, IndexedDB, WebSQL или вообще персист на сервер через REST. Я спроектировал это так, что модуль получает на вход абстрактную алгебру
StorageAlgebra, у которой эффект синхронного или асинхронного вычисления вынесен в некую монаду M, о которой модуль знать ничего не знает до тех пор, пока его не запустят с конкретным инстансом нужного стораджа. По сути, мне пришлось реализовать паттерн Tagless Final для этого стораджа. В тайпскрипте, как в языке, где нет типов с дырками, это отдельная боль. И вот, вроде бы, счастье — тесты зелёные, можно подсовывать как синхронные, так и асинхронные алгебры, и всё будет работать…Но есть нюанс. В рамках продвигаемой архитектуры приложений я требую, чтобы все работы с хранилищем и сетевыми запросами происходили в рамках
redux-saga. Которые сами по себе асинхронные. И этот факт наглухо перечёркивает всю предполагаемую гибкость. Мы уже живём в асинхронном контексте, нет пути назад. Поэтому я выкинул весь код с TF, попутно избавив себя от необходимости объяснять его коллегам из вверенных мне команд, оставив в качестве единого для всех интерфейса пакет localForage.Мораль: нельзя позволять себе терять виденье общей картины, углубляясь в столь приятные (но порой ненужные) технические детали.
Такие дела.