Стендап Сьогодні
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
Пости з тегом #Clojure
14.09.2022
Мій досвід з Clojure
🧙☕🏕️ Сьогодні якось згадалась між словом мова Clojure, яку я обожнюю, хоч не використовую.
У мене цікава ситуація з Clojure - з одного боку, вона мені подобається як естетично, так і функціонально. Але з іншого боку, для будь-якої задачі знаходиться мова краща. Так що я на Clojure нічого не пишу — хоча залишилась пара живих проєктів, такі як дисплей погоди.
А проте, досвід, набутий з Clojure, залишився зі мною на довгі роки. Тому, на мою думку, цю мову корисно випробувати кожному інженеру.
- Clojure - функціональна мова програмування. З мого досвіду, як не найпростіша для освоєння новачком. Тут я тільки скажу, що з функціонального програмування виріс React. ФП навчить вас краще розуміти потоки даних у вашому коді.
- Clojure- це лісп. І, мабуть, знов найдоступніший. Лісп навчить вас писати чудові DSL, бо в цій мові можливості розширення на порядок кращі, ніж в будь-якій “нормальній” мові.
- Clojure можна використовувати як з Java, так і з JavaScript, для написання фронтенду. Фреймворк re-frame надихнув бібліотеку reselect, між іншим.
- Творець Clojure - Річ Хікі — винахідник терміну “програмування в гамаці” та інших філософських роздумів. Як цінитель гамаків, не можу його не підтримувати.
Якщо хочеться глянути на 50 рядків красивого коду на Clojure, пропоную мою імплементацію OAuth.
15.06.2023
Сучасний стан розробки на ClojureScript
На Реддіті побачив запитання про засоби перевірки OPML файлів для RSS. Ба, думаю, так я ж такий писав. От тільки давно. Та є два нюанси. По-перше, він був розміщений на моєму виділеному сервері, який я давно припинив підтримувати (бо складно). По-друге, написаний він був на Clojure/ClojureScript, бо в ту епоху (у 2015) мені було цікаво кудись його застосувати.
Куди розмістити зараз — в мене вибір один - Firebase. Бо дешево та просто. Але Firebase на бекенді підтримує тільки JavaScript. Не проблема, в теорії, бо бекенд можна портанути з Clojure на ClojureScript. Знайшов гарну інструкцію, як запустити ClojureScript на Firebase Functions, та це дійсно швидко спрацювало.
До переписування бекенду я поки не дійшов, бо ще треба оновити фронтенд. Майже все, що я використовував 8 років тому, померло. Зʼявилися нові інструменти. Замість Figwheel для збірки проєктів тепер є Shadow CLJS. Дуже приємно працює, з простими налаштуваннями робить дві збірки — бекенд та фронтенд, сам завантажує залежності (зі світу Clojure; ті, що на Javascript, завантажує yarn, як звичайно), в браузері наживо оновлює. По цьому питань взагалі нема.
Фреймворк для фронтенду Om теж більше не підтримується. Вони самі рекомендують переїхати на Fulcro. Це дуже складна система зі власними абстракціями та з привʼязкою до свого фреймворку на бекенді. В мене найбільше питань по тому, що для вибірки даних зі стану використовується EQL. Для простого додатка це зайві ускладнення.
Зате re-frame все ще живий. Re-frame це як React+Redux+Reselect в красивій функціональній абстракції. Його я б і рекомендував брати, якщо захочеш спробувати Clojure. Це, напевно, найкрутіше що є з практичних міркувань.
Для форматування коду мені дуже подобався parinfer, але й він більше не підтримується. Для розробки в VSCode є доповнення Calva з власним форматувальником — до нього треба звикнути, але задачу балансування дужок, в цілому, він виконує.
14.06.2025
Як я робив проєкт аналізу автобусного руху
Років з 10 чи трохи більше тому в Дніпрі зʼявилася перша система відстеження руху автобусів - transit.in.ua (давно припинив існування, зараз там якийсь спам.) Вона показувала на карті координати автобусів… але більше не вміла нічого. Зокрема, не було там прогнозу прибуття автобуса.
Я якийсь час намагався цей прогноз запрограмувати. Виявилося, не так це легко! Втім, то був один з моїх експериментів на Clojure, та я хоч в цьому плані отримав користь.
Головна проблема ось в чому. Координати автобуса це є точка. Маршрут це є ламана. Точку потрібно перекласти в систему координат маршруту. Тобто отримати значення від 0 до 1, що показує пересування автобуса за маршрутом.
І тут далі… координати майже ніколи з ламаною не збігаються, бо такий реальний світ. Ба більше, за координатою не зрозуміло, в якому напрямку рухається автобус, бо через похибку її можна віднести як до прямого, так і до зворотного маршруту. (Зазвичай маршрути малюються як кільце, а не тільки лінія з кінця в кінець.)
Отже, доводилося також стежити за рухом точки ламаною та дивитися, чи буде він “у відʼємному напрямку”; тоді ми помилилися (“не вгадали”) з місцем — та треба брати місце на зворотному відрізку. Як можна уявити, коли в системі зʼявляється час, то вся архітектура ускладнюється.
А особливо допікав шум — автобуси, що стоять в тупику, ті, що поїхали в депо, або просто неправильно налаштували датчик. Я, напевно, тоді ще не зрозумів, що краще почати з часткового рішення, ніж намагатися покрити всі варіанти, та зрештою так і не розвʼязав цю задачу. А тепер, бачите, різні компанії вже розвʼязали.
Поставив питання — а де зараз взяти таку інформацію? Бо нині хто хочеш показує автобуси, включаючи Google Maps - але при тому самі трекери встановлює хтось один (влада?) Отже, повинне бути “джерело істини”. Та воно є! Відкрив для себе портал data.gov.ua, на якому, проміж іншим, є й API транспорту Дніпра, та й багатьох інших міст. Дуже цікаво!
15.06.2025
Метапрограмування та особливий стиль Clojure
В Clojure, абсолютно впевнено, код є даними. Насамперед для цього потрібно, щоб код не відрізнявся від даних на вигляд: саме для цього в ліспах такий дивакуватий синтаксис, де код не має особливих відзнак. Будь-яка конструкція з дужок може бути як “нормальним кодом”, так і вхідними даними для макроса, який інтерпретує цю конструкцію аж будь-яким чином.
Є макроси ситуативні: defroutes
чи html5
тощо. Вони нагадують схожі конструкції в Ruby чи JavaScript, бо принаймні не ставлять задачі вигадати нові мовні конструкції. Але то тільки верхівка макросів на Clojure… Бо справжній айсберг то макроси, що спрощують деяку сталу мовну конструкцію. Таких повно в самій стандартній бібліотеці. Так званих спеціальних форм, тобто дійсно “аксіоматичного” коду, який напряму розуміється компілятором, лише з десяток. А всі інші — як cond, аналог switch-case
, вже реалізовані як макроси.
Але звісно, стандартною бібліотекою все тільки починається. Бо все можна переробити під себе, або принаймні знайти вже перероблене.
Як приклад: бібліотека swiss-arrows. В Clojure вже є доволі проста протяжна форма (-> x f g)
, що еквівалентно (g (f x))
. (Це лише один спосіб спростити вкладені виклики.) Але ця бібліотека додає макроси для набагато складніших ситуацій, як-от діамантова вудка (sic) -<><
, що виконує одну форму та поширює результат до списку інших, можливо й в паралелі: (-<>< (+ 1 2) [<> 3] [4 <>])
.
Не знаючи макроса, під час просто неможливо зрозуміти, що він робить. (Бо ота вудка нічим не видає своєї дії.) Такі можливості створюють екосистему, де від проєкту до проєкту код може відрізнятися радикально. Це й гарно і погано водночас.
Гарно, бо можна ліпити код під себе, та майже нічого не стоятиме поперек шляху. Та повір, знаходити (чи створювати) та використовувати зручні макроси — на Clojure частина повсякденної інженерії, та без неї виходитиме багатослівно та теж незрозуміло.
Погано, бо немає ніякого стандарту. Ідіоми Clojure містять більш загальні твердження, як-от “пиши функціональний код” та “використовуй функції вищого порядку.” Коли шукаєш приклади чи читаєш код бібліотек, часто здається, що вони написані різними мовами (та певною мірою, так і є!)
Чимсь все це нагадує бібліотеку Lodash, бо там теж можна писати фільтри та інші параметри різними спрощеними шляхами: _.map(xs, ["foo" bar])
. Але я б радив спробувати Clojure, щоб на собі відчути цю силу вигадувати код таким, яким це зручно для твого проєкту.