brain_dump_etc
637 subscribers
99 photos
4 videos
3 files
383 links
Дампы мыслей, свалка ссылок, программизмы, вот это всё (ВНИМАНИЕ: много вкусовщины!)

Автор надампленых мыслей: @astynax

Чат к каналу: https://t.me/brain_dump_chat
Плейлист трансляций: https://youtube.com/playlist?list=PLUFoWyWge7mrg4GqHLMZV62gGC912PCGq
Download Telegram
Я веду свои заметки в Org Mode, потихоньку перетаскиваю то, что раньше просто лежало в огромных файлах, в карточки Org Roam, линкую всё это дело.

То, что пишу в канал (уже в каналы), веду в больших файлах в виде outline со списком опубликованных записей и идей на будущее. Опубликованные записи помечены как DONE и имеют дату публикации. Отсортированы в порядке публикации. "Идеи" идут следом. Не идеально, но "мне удобно".

Для побочного канала решил минимально уменьшить количество препятствий, отделяющих меня от записывания мыслей. Для этого прямо в inbox-файле завёл поддерево "brain_leakage_etc" — у меня этот файл открывается по хоткею, удобно сразу мочь начать писать. Но ведь ветки в дерево нужно добавлять, проставлять дату — это всё излишнее трение!

"Нужно автоматизировать", подумал как-то я — "вот бы мне «кнопку» — ту самую «сделать хорошо»". И положил прямо в дерево исполняемый блок кода на Emacs Lisp, ведь Org Mode такое тоже умеет. Вот такой код:

(org-get-heading)
(org-goto-first-child)
(org-insert-heading '(16)) ;; C-u C-u
(insert "IN-PROGRESS ")
(insert (format-time-string "[%Y-%m-%d] "))
(insert "\n")
(org-narrow-to-subtree)

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

Теперь я встаю курсором на это блок кода, жму Ctrl+C Ctrl+C и оказываюсь в режиме написания нового текста!

Да, можно было сложить весь код в (progn) и сделать elisp-ссылку, которая работала бы точно так же, но я пока ещё отлаживаю flow, так что мне не мешает видеть этот кусочек кода (его всё равно можно свернуть). Можно даже было в конфиг мой функцию положить. Вот только мне приятно, что я могу именно в этом конкретном документе запрограммировать нужное мне поведение!

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

Если кому всё ещё интересно, что за '(16), могу рассказать. У Emacs есть возможность параметризовать действие числовым аргументом, который обычно означает количество повторов действия. Скажем, если сочетание M-d (это Alt+D по-имаксовски) удаляет слово под курсором, то C-u 8 M-d удалит 8 слов.

А если нажать только C-u (Ctrl+U), то это означает "повторить четыре раза". Почему 4? Так исторически сложилось. Но это же одиночное C-u часто используется просто как указание выполнить "слегка альтернативное действие": открыть ссылку не во внутреннем браузере, а во внешнем и тому подобное.

Иногда встречаются действия с "альтернативными альтернативами" (очень редко, к счастью), и org-insert-heading — как раз такое. Без модификаторов новый узел outline вставляется над текущим, с одиночным модификатором узел вставляется под текущим, а с двойным модификатором — в конце списка узлов родительского узла. Вот только мне-то функцию нужно было вызывать из кода. В таких случаях нужно передавать "число повторов" как синглтон-список. А "четырежды четыре повтора", это как раз те самые 16 :)
🔥7🤔2
​​Вчера поизучал то, что пишут про Bangle JS 2 — это такие часы на базе ARM от Nordic, с немножко цветным memory LCD как у приснопамятных Pebble, GPS, датчиком пульса и прочими прелестями.

Программируются часики на JS, увы. Зато прямо из браузера. Да и Espruino — тамошний интерпретатор JS — нынче довольно стабильный, вроде как. Да и inline C можно вставлять в код, так что можно писать что-то экономичное. Часы, как говорят, могут жить на одной зарядке неделю-две, что очень даже достойно. Есть возможность подключать часы к телефону и использовать с популярными программами вроде GadgetBridge. И в целом всё, что можно было открыть, открыто, что внушает некоторые надежды на то, что устройство проживёт дольше, чем прожили Pebble.

На сабреддите Bangle JS 2 сравнивают с PineTime (c Pebble тоже сравнивают) PineTime — это уже часы от Pine64, которые знамениты своими подчёркнуто открытыми железками вроде телефонов, читалок, ноутбуков. Как реддитовцы отмечают, у Pine64 лучше обстоят дела с качеством производства, часы более "вылизаны". Да и FreeRTOS внутри PineTime выглядит более серьёзно (а ещё там LVGL интерфейсы рисует и вообще стек интересный). Но вот экран у PineTime — IPS. И вот это меня очень печалит, потому что на носимых девайсах трансфлексивные memory LCD мне гораздо больше нравятся!

Из интересных проектов есть ещё Sensor Watch, но это уже совершенно другой весовой категории штука. Это новая "материнская плата" для очень популярных классических часов Casio F-91W (и другой модели с совместимой начинкой). Используется оригинальный сегментный экран, оригинальные кнопки, даже батарейка используется та же. Зато можно напрограммировать себе таймеров, секундомеров, фаз луны, генераторов ключей для TOTP. Ещё есть возможность добавить сенсор вроде температурного, но нет уверенности, что сенсоров таких будет много. Такой себе проектик для больших любителей Casio, желающих немного покастомизировать часы, сохранив олдскульность :)

Вот такие проблемы выбора. А пока я продолжаю ходить со своим MiBand и ждать идеальной лично для меня замены для Pebble.
👍11🤔1
Я тут завтра буду стримить Котлин, внезапно. Буду на Jetpack Compose делать десктопное приложение — игру 2048 реализую.

Цель состоит в том, чтобы показать, что на Котлине не только вебчик пишут и не всегда на Spring :Р

Правда котлинист из меня странный, поэтому писать буду так, как мне нравится :)
👍8🔥3🤔2
Постримил Котлин вчера нормально, мне кажется. Хоть без грабель и не обошлось даже там, где, казалось бы, соломки достаточно подстелено было :) В описании к видео можете найти ссылку на код.

А ещё сегодня второй день Advent of Code '2022, если ещё не начали участвовать, зову присоединяться! Я уже который год участвую, правда, с переменным успехом: не каждый раз получается найти время в двадцатых числах октября, а там как раз задачки посложнее начинаются, так что у меня бывали бодрые начала, но уходил в итоге не дальше середины :)

Если вдруг кто решил/решит на #Haskell решать задачи, советую пробежаться глазами по этой статье: Some tips and tricks for doing Advent of Code with Haskell Советы в ней даются совсем новичковые, но тем не менее, кое-какие из упомянутых практик я сам открыл для себя за годы участия.
🔥5👍2
Недавно в одном из чатов вспоминал, когда же я пользовался Windows нормально, а не только для запуска Steam. Где-то года с 2010 я на Linux перешёл в качестве домашней ОС, а до этого сидел на WinXP, но даже тогда у меня был очень странный Windows. Классическая тема оформления. Ни одного ярлыка на Dеsktop. Total Commander — вот что было моей настоящей оболочкой! Я вообще жил в двухпанельных файловых менеджерах, начиная с MS-DOS в середине 90-х и заканчивая началом нулевых уже на Windows. Так что вспомнить про TC было приятно: я не просто его использовал, я регулярно дорабатывал TC, чтобы тот соответствовал моему пониманию "идеальной ОС"!

Но для начала я признаюсь кое-в-чём: я TC так и не купил :( Всё откладывал до "первой зарплаты", чтобы, наконец-то, заказать себе фирменную дискетку. Сперва использовал ключик с дисков с софтом, а затем и из интернетов. Но в какой-то момент воспользовался тем, что Гислер (автор программы) разрешил бедным студентам использовать безвозмездно — коль скоро те не будут добывать ключи, а продолжат при запуске программы нажимать те самые кнопки "1", "2" и "3" (напомню, при запуске программа просила нажать выбранную ею случайно кнопку — одну из трёх на выбор). Ну так вот, нажимал я, нажимал кнопки эти какое-то время, а потом решил это действие автоматизировать :)

Написал свой launcher, который ждал, пока TC запустится и покажет окошко с кнопками, искал элемент управления, который содержал название выбранной кнопки, а потом, собственно, нажимал кнопку. Минимум жонглирования WinAPI и вы даже не видите то самое окно, а сразу начинаете работать! Писал я этот лаунчер на Delphi, как тогда у меня водилось, и тогда я уже освоил кое-что из WinAPI и программировал на "сыром Delphi language" без формочек и прочего мышиного программирования.

Со временем launcher научился запускать "ровно одну копию" TC, потом добавилась возможность открывать директорию во вкладке уже запущенного коммандера, если лаунчер получал путь в качестве параметра — при drag'n'drop на иконку на панели задач или через отправку в "Send to…". Тесная интеграция с ОС!

Ещё у моего TC были переключаемые панели инструментов, потому что на одну все кнопки уже не влезали. А работало переключение потому, что показывал новую панель инструментов при нажатии на кнопку на оригинальной панели, если вместо программы для запуска вы кнопке назначали файл новой панели — настоящее инженерное решение :). Когда мой TC оброс кучкой portable software, такие панели пригодились! Правда, пришлось понарисовать изрядное количество пиктограмм.

И что было особенно приятно, даже тогда, когда добавилась поддержка Windows Registry, TotalCommander позволял себя настраивать через INI-файл, в том числе лежащий в заданной вами директории. Достаточно было указать файл конфигурации в командной строке — этим тоже мой launcher занимался. В какой-то момент появилась поддержка разделяемых файлов конфигурации и мой большущий конфиг был успешно распилен на десяток отдельных файлов!

Эх, сколько всего было ещё понакручено… Выбиралка редактора по расширению, например. Сам TC тогда ещё вызывал один редактор для всего, хотя просмотрщики были настраиваемыми. Ещё я использовал подкрашивание файлов и директорий более яркими цветами, если в описании файла или директории в файле descript.ion встречался соответствующий тег. Это позволяло, скажем, отмечать текущий эпизод сериала, чтобы в следующий раз начать с того же места.

В какой-то момент в мой набор портативного софта добавились mplayer и даже GVim — я, сам того не зная, приблизился к Linux максимально :) Собственно, во многом поэтому было проще соскакивать с Windows, ведь я практически не пользовался рекомендованными производителем средствами. А уже на Linux я пробовал использовать TC под Wine, но в какой-то момент понял, что большой менеджер файлов мне не нужен, а когда изредка нужно бывает что-то поменеджить, нынче я беру ranger.
👍15🔥6
​​Я уже который год участвую в Advent of Code. Планирую в этот раз дойти до конца, тогда это будет мой второй успешный финиш.

Пока решаю как обычно на Haskell. И параллельно на Common Lisp, раз уж книжек по нему почитал в этом году — практикую loop, а вчера даже ООП, макросами обмазанный применил :)

Надеюсь дотащить оба языка до конца, но решать приходится два раза: на Haskell как обычно зипперы и иммутабельность, а вот на CL процедурщина, мутации, деструктивные присваивания в многомерные массивы. Но тем и интереснее. На Python, например, тоже мог бы решать, но не тянет — что я, апдейтов словарей словарей списков на нём не делал?

Вот стримить решения я пока не пробовал. Но может быть позовут показательно решить для "Контура": у них бодро идёт процесс, день-в-день, с решениями от разных авторов на разных языках!

У JetBrains тоже есть плейлист с решениями на Kotlin и последующие дни даже анонсированы — умеют же в привлечение внимания подписчиков!

А тут можно посмотреть на решения задач первых двух дней на Clojure, причём с использованием не только стандартной библиотеки, но и пакета specter — это такая "пост-стандартная библиотека" для всяческих сложных трансформаций над сложносоставными данными. Я specter себе "закладывал", но сам пока не добрался, успел только упомянуть в докладе, так что мне лично было интересно посмотреть на применение пакетика на практике.

Забавно было увидеть, как автор видео из предыдущего абзаца автоматизировал себе загрузку данных. У него файлы с данными скачиваются скриптом через передачу session cookie, я до такого ещё не дошёл. Но зато в Emacs в .org-файлике, который у меня как Inbox работает, я сделал выполняемые блоки, один из которых берёт ~/Downloads/input и под нужным именем кладёт в два репозитория, попутно создавая болванки для программок, а ещё два скрипта открывают по инстансу Emacs в каждом из проектов. Я даже темплейты для commit messages в .git подложил, чтобы не писать руками "add: solution for the day #"! Вот так и развлекаюсь :P
🔥16👍3
​​Ну вот я и закончил Advent of Code с 50 звёздами! В первый раз дошёл до конца и даже вовремя, с чем себя и поздравляю :)

Что я могу сказать… в этом году было проще, чем бывало раньше. Да, я буксовал пару так, что приходилось переписывать решение задачи по пять раз и даже прогонять чужие решения на моих данных, чтобы найти баги. А вот именно решения чужие я не подсматривал, только пару раз заглянул уже после того, как своё получил. И лучше бы не заглядывал, очень уж там страшненький код встречается ;)

По качеству заданий могу тоже сказать "бывало и интереснее". Я уж молчу про 2019 год, когда нужно было свой интерпретатор выдуманного языка реализовывать и расширять его функциональность от задачи к задаче. Но и в целом были дежурные задачи на клеточные автоматы, интервалы, модульную арифметику — с одной стороны это то самое "знаем и (не)любим" (люблю КА, не люблю формулы), с другой именно новизны не хватило в этот раз. Впрочем, парочка задач действительно понравилась, так что в целом я доволен!

Второй набор решений тех же задач, но на Common Lisp я не дотянул, остановился дне на восемнадцатом, кажется. Однако пользу от "набивания руки" на жонглировании лисповыми loop я получил. И даже микро-библиотечку парсер-комбинаторов написал в процессе! В будущем какие-то задачи я добью, возможно: интересно порешать их именно императивно, на изменяемых массивах (уже предвкушаю чад отладки) и ООП в лице CLOS.

На будущий год решил попробовать решить сколько-то задач на Emacs Lisp (параллельно с Haskell, само собой). Тут уже мне хочется посмотреть, каково это — использовать в роли "структуры данных" обычный имаксовый буфер со всеми возможностями вроде "переместить курсор на три слова вперёд" и "искать следующее вхождение подстроки". Я посмотрел, как Gavin Freeborn решает первую задачку, и захотелось тоже попробовать.
🔥25👍10
​​Под конец прошлого года вышла статья про то, как автор сделал карту для Doom, которая содержит машину, складывающую десятичные числа. И работает этот своеобразный калькулятор не только на современных вариантах оригинального движка Doom, но даже на Vanilla Doom 2 без каких либо дополнений и модификаций!

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

Даже про само по себе кодирование булевой логики читать интересно, но автор не пожалел времени и снабдил статью не только иллюстрациями и анимациями, но и приложил интерактивный симулятор, показывающий то, как происходит суммирование и формирование ответа на "сегментированном индикаторе" — красота!

А ещё кому-то будет интересно почитать про то, как автор генерировал WAD-файл с картой, а делал он это с помощью… #Clojure, которая позволила и DSL использовать для описания диаграмм решений, и на ней же был реализован оптимизатор "кода", позволяющий сэкономить место на карте.
🔥22
Буквально позавчера в Steam вышла игра Kandria. По стилистике игра напоминает классику вроде Flashback) и Another World), а в плане игрового процесса это "нарративный платформер" в атмосфере постапокалипсиса. Придётся немножко подраться и множко попрыгать и полазить по стенам пещер и остовов домов.

"Ну игра и игра", спросите вы, зачем я про неё пишу здесь? Отвечаю: потому что игра написана на… Common Lisp! Да, хорошо (для indie, как минимум) выглядящая и звучащая игра доделана и выпущена в Steam. И создана Kandria буквально одним человеком — и движок, и код игры (Open Source!), и даже графика! Вот такие смельчаки ходят среди нас :)
🔥19👍1
​​Я тут немножко записываю то, как решаю задачки Advent of Code 2016 на Common Lisp. Навёрстываю упущенное, так сказать. Пока хватает стандартной библиотеки, но может быть свой парсер притащу в итоге — получился вполне удобным. Ещё надо будет поиграться с альтернативными наборами батареек вроде Radical Utilities, пусть даже большая часть подобных библиотек — оголтелая вкусовщина :)

Кстати, если вам нравится читать всякие истории из жизни программистов старой школы, можете глянуть на эту статью: "Lisping at JPL Revisited". Автор пишет о том, что он думает о прошлом себе, написавшем оригинальную статью "Lisping at JPL" в начале нулевых, и как эволюционировали его (автора) отношения с Common Lisp. И оригинальную статью почитайте тоже: она рассказывает про программирование марсианских роверов на Lisp.

А кстати эта статья приходится потому, что Rondam Ramblings (так автора зовут) программирует вот уже почти сорок лет на своём языке, который он построил на основе CL — очень "лисперская" история и тоже вся наполнена вкусовщиной. При этом автор считает, что именно такие личные истории и привели к тому, что экосистема у Common Lisp ныне сильно фрагментирована. Так что "критику лиспов от лица лиспера" вы в статье тоже найдёте.

P.S. В процессе записывания процесса решения у меня пока обнаруживаются всякие проблемы вроде пропадания кадров в записях стримов силами Telegram, с которым раньше не было проблем. Но в принципе оно смотрибельно, да и с третьего видео я перешёл на локальную запись с помощью OBS, так что пропуски кадров должны уйти в прошлое. И OBS хотя бы не вставляет заглушки свои в ролик, как это телеграм делает.
👍9🤔2🔥1
Раз уж я тут с Common Lisp играюсь в последнее время и сюда об этом пишу, то прорекламирую один YouTube­канал: "IT Муравейник".

Автор недавно начал рассказывать про то, как вообще живётся в мире CL, как его готовить и с чем вприкуску есть. А сегодня Александр выложил ролик про библиотечку cl-reex в формате "сегодня я поковырял вот это вот" — у автора раньше уже был заход в "рассматривание по библиотеке в день" и очень даже длинный, в 220 дней (мне бы так)!

Так вот, у меня от cl-reex возник тот самый "вьетнамский флешбэк": вспомнилось, как я проходил на Coursera курс "Functional Program Design in Scala", когда он только появился, в 2012 (!) — с отличием закончил, между прочим! Курс до сих пор существует и в одной из частей знакомит с реактивщиной в Rx­стиле с наблюдателями и подписками. Мне тогда эта идея вполне понравилась, во многом потому, что в курсе подавалась интересно.

Потом я, правда, видал примеры "серьёзного" использования Rx, и они мне понравились не так сильно. Мне гораздо больше нравится FRP, с тех пор, как я с ним поигрался в Elm, даже доклады делал про это всё. А потом был не рад, когда FRP из Elm выплили. Но это, как говорится, уже совсем другая история.

Однако, не могу не отметить, что в контексте с CL реактивщина в стиле Rx смотрится неплохо! Потому что язык процедурный, мутировать состояние очень даже принято. Вот и сеть подписок строится путём оформления подписок для существующих наблюдателей. Зато макросы позволяют довольно приятно разгрузить синтаксис:

(defparameter observer
(rx:make-observer
(rx:on-next (x) (print x))
(rx:on-error (x) (format t "error: ~S~%" x))
(rx:on-completed () (print "completed")) ))

Никаких вложенных вызовов, даже лямбды спрятаны за клозами вроде rx:on-next — DSL в лучшем виде, если вы вообще любите такое, конечно.

Надо будет попробовать написать какую-нибудь игрушку с логикой на cl-reex. Только сначала нужно найти библиотеку, которая с канвой работает не слишком многословно. Может быть в "IT Муравейнике" проскользнёт? :)
👍11
​​У меня на той неделе намечается стрим. Будет не столько сложная вёрстка какая-то, сколько просто разработка под браузер в целом: приложение с состоянием, local storage, походами в публичный API за данными. Так что будет не то чтобы очень красиво, но зато разнообразно :Р

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

Изначально планировалась книга про три языка: TS, ClJS и PureScript, но мои соавторы пока не готовы публиковать свои порции, а я уже написал достаточно, чтобы имело смысл выложить в виде GitBook. Может ещё и Patreon какой-нить прикручу — вдруг кому понравится. А большая книга про три языка выйдет, когда выйдет. Может быть я сам, когда часть про ClJS добью, попробую помочь коллегам с TS или PS.
🔥19👍5🤔1
​​Постримил вторую часть приключений с ClojureScript. Сделал забор данных о покемонах через GraphQL, уложил оные в DataScript, попробовал погонять запросы. Естественно, наступил на половину граблей, даже REPL подвесил разок, но в целом доволен. Теперь нужно придумать, как many-to-many связи между "моделями" разложить на тройки, но это я в фоне попилю к следующему вторнику, когда третий стрим будет.

Кстати, backend у PokeAPI на Python/Django написан. А GraphQL делается силами Hasura, а это, на минуточку, уже проект, реализованный на Haskell! (Если что, Hasura — это такая штука, превращающая вашу базу в *PostgreSQL* в GraphQL endpoint с админкой и правами). Вместе с моим проектом на ClJS получается настоящий зоопарк :)
🔥10
​​Третью часть вчера постримил. Как всегда, не без граблей :) На этот раз подвёл PokeAPI — у них прилег GraphQL backend, о чём мне радостно сообщил CloudFlare прямо перед стримом.

А ведь я хотел сдампить себе выдачу, чтобы локальную копию иметь и не нагружать сервис лишний раз! Но, как в анекдоте про бэкапы, пришлось перейти из лагеря тех, кто ещё не делает, в лагерь тех, кто уже делает :)

Я даже пытался по-быстрому сдампить то, что у меня было сохранено на другим компе в запущенном REPL. Но в случае ClJS не так-то просто взять и что-то осмысленное сделать со структурой в несколько мегабайт. Я пробовал воткнуть в DOM ноду с <pre></pre>, чтобы потом скопипастить содержимое в файл. Но вставка выдала копию значения в REPL в качестве эха и это был конец: REPL помер в попытке вывести эти самые мегабайты — и со стороны Emacs, и в консоли браузера. Иными словами, не получилось сдампить, так что пришлось мокать.

В процессе мокания наткнулся на пресловутый nil punning: когда спуск вглубь структуры натыкается на nil, вы не получаете ошибку, а вместо этого получаете nil в качестве результата. Это удобно, когда ты того хочешь, и неудобно, когда не хочешь. Но уж таков путь (в Clojure, как минимум). Да, кложуристы сказали бы (кое-кто таки сказал ;)), мол, надо было сразу спеку cделать. Да, надо было. Может быть и сделаю в следующей серии!

В любом случае, я сделал таки тестовые данные. Это позволило порешать проблему с дублированием строк в выборке, предполагающей JOIN "табличек" в Datascript, связанных как "один-ко-многим". Силами БД я это не стал решать, просто пожонглировал мапками, но на то у нас и Data-Oriented Programming, чтобы обходиться обобщёнными структурами данных и превращать неудобные внешние данные в удобные внутренние посредством манипуляций над этими самыми структурами!
🔥8👍1
​​Вот и четвёртая часть.

Сегодня пробовал заменить react-based вёрстку на enfocus — это когда режешь селекторами готовый HTML-пример, а потом в прорези данные подставляешь. В своё время enlive и enfocus были вполне себе, а нынче, увы, enfocus "отгнил" — использует куски из google closure, которых и нет давно.

Попробовал более свежую (но не сильно) инкарнацию, которая делегирует "рендеринг" в Reagent или Om. Но и эта либа не завелась, потому что reagent вперёд убежал и тоже кое-какие из API-функций потерял в итоге. Итог выглядит так: всё, что было в экосистеме ClJS и отличалось от React, не выдержало конкуренции. Увы и ах.

Но не только провалы сегодня были. Были и успехи. Взял и натянул clojure.spec на входной JSON. Пусть будет, потом пригодится, когда буду внешнее представление во внутреннее перегонять — всё, как Data-Oriented Programming нам завещал!

В серии планируется заключительная трансляция про backend — для контраста с фронтом и просто потому, что там как-то макросы повыразительнее смотрятся (compojure возьму по олдскулу. Или bidi, как пойдёт).
👍5
​​Кстати, стримлю в рамках нашего клуба далеко не только я. На днях, например, у нас был гость, рассказавший популярно про Nix.

Я лично с Nix знаком давно, но всё равно кое-что новое почерпнул: узнал про Nixery. Это такой способ получить OCI­совместимый контейнер, содержащий заданные пакеты из Nix. Если вы знакомы с Nix, то можете считать, что это "nix-shell -p …", только в контейнере!

Для чего такое может быть нужно? Чтобы разово что-то запустить в песочнице, не подготавливая предварительно Dockerfile. Скажем, нужно вам что-то конвертировать с помощью pandoc, но оный у вас не установлен и устанавливать его не хочется ради однократного использования.

Да, конкретно образа с pandoc есть на DockerHub. Но что если вам хочется применить к документу фильтр, написанный, к примеру, на Racket? Придётся либо в shell внутри контейнера что-то доустанавливать, либо написать таки Dockerfile.

И я не хочу сказать, что написание Dockerfile — это плохой путь! Вот только Nixery позволяет получить сразу контейнер с установленными пакетами pandoc + racket без какого-либо конфигурирования: вам достаточно указать имя контейнера вида "nixery.dev/shell/pandoc/racket"! Слои таких контейнеров построены силами Nix, так что если вы будете запускать пересекающиеся множества пакетов, общие слои будут использованы повторно — это тоже очень приятно!

Но стоит понимать, что Nixery не призван заменить написание Dockerfile или описание контейнеров силами самого Nix. Например, я пока не понял, можно ли зафиксировать версию nixpkgs, скажем, в теге контейнера. С другой стороны само наличие хранилища разных версий всех пакетов Nix звучит как дорогая затея.

Так что я буду смотреть на Nixery просто как на логичное дополнение для nix-shell "вне проекта", такое же "нестабильное", но полезное для разовых экспериментов.
👍5
Постримил вчера завершающий эпизод, как и планировалось, про backend (UPD: в значении "server side") для контраста. Взял привычные ring+compojure, проект завёл через leiningen. Да, я всё ещё готовлю Clojure именно так :P

И нормально получилось, надо сказать! Всё используется так, как я запомнил десять лет назад, и это приятное ощущение постоянства. Да, видно, что где-то что-то причесали, документации стало больше, а велосипедов меньше. Но сам подход "backend — это функция request → response" всё ещё отлично работает. Так делают и в Python в виде WSGI, и в Haskell в виде warp/WAI. Даже middleware одинаково сделаны — как функции, принимающие старую функцию­-обработчик и возвращающие новую.

Даже рассуждать о сервере, как о "функции", очень удобно: это как бы вынесенный из браузера вовне обработчик события нажатия на кнопку! Жаль, что на клиентской стороне не получится так просто спрятать вызов сервера за внешне синхронным вызовом callback.

Впрочем, макросами можно попробовать разбить такой "обработчик нажатия на кнопку" на собственно посылку запроса и continuation, обрабатывающий ответ на оный. И такие попытки уже есть! Например, проект electric — обязательно посмотрите, как выглядит тамошний DSL, позволяющий совместить в едином с виду фрагменте кода вызовы функций на сервере и клиенте с передачей результатов между ними.

А я пока серию стримов закончил. Но только лишь до следующего раза :)
🔥5
Нагулял на днях идею: сделать web-app, который бы генерировал бесконечное подземелье. Причём нет цели получить проходимы лабиринт, достаточно того, чтобы оно интересно выглядело. Я вижу конечный результат в виде плавно прокручивающейся вниз карты, достраиваемой по мере достижения текущего конца. В процессе периодически менялись бы декорации, чтобы не так быстро наскучивало. Эдакий Screen Saver.

А придумал я эту штуку как способ заставить себя рисовать маленькие картинки чем чаще, тем лучше. Вот и будет стимул рисовать тайлы в стиле разных биомов, придумывать по нескольку альтернатив для одного и того же кусочка "шахта сверху-­вниз с ответвлением вправо". Это всё можно завернуть в Web­-интерфейс, который позволял бы загружать тайлы и размечать, указывая

- наличие или отсутствие выхода на каждой с четырёх сторон, чтобы мочь соединять
- тему/биом тайла, чтобы использовать единую тему для "геологического слоя"
- частоту появления, чтобы показывать секретные тайлы пореже

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

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

Или можем коллективно поделать, если кто-то поучиться хочет на вполне чётко очерченном проекте. Можно сделать на Haskell/Yesod, Python/Django, Clojure/ClJS/whatever. Тут я готов с менторской стороны выступать, у самого хватит запалу только на небольшую часть кода.
👍9🔥1
Эх, опять телеграм скушал картинку, как только я пошёл текст подредактировть... Вощм, вот такие вот каракули я хочу рисовать и использовать для генерации подземелий. Для той штуки, которая описана выше.
👍11😱1💩1
Я, как в далёком прошлом пользователь Windows со стажем, конечно же слушал музыку с помощью Winamp. В основном сидел на второй версии, потом пересел на AIMP, затем на Foobar2000. Даже свой плеер писал с системой плагинов и рекурсивными плейлистами — как-нибудь напишу про это.

Плееров было много, но для меня Winamp так о остался первой программой, которая показала, насколько необычно может выглядеть ПО на Windows. И пусть тот же Sonique) появился на моём горизонте не сильно позже, а выглядел гораздо более футуристично, да и Windows Media Player тоже в какой-то момент научился "шкуры" менять, но к тому моменту я уже знал, что так можно. И знал, как это делается — даже отверстия в окнах научился делать средствами WinAPI и regions.

В народе, конечно же, что Winamp был любим ещё и за то, что мог ещё и менять внешний вид. Это для многих была, опять же, первая программа, внешний вид которой можно было выбирать по вкусу — чтобы плеер выглядел, как постер к "Зачарованным", скажем. И разнообразие шкурок было столь велико потому, что формат оных был дружественным любому начинающему творцу, умеющему применять WinZIP и MS Paint — шкурки были ZIP-архивами с BMP-файлами внутри!

Некоторую сложность для художников по коже могли представлять текстовые конфигурационные файлы, содержащие помимо прочих метаданных описание того, какими цветами должен был мигать анализатор спектра. Цвета задавались в 16-ричном представлении RGB-цветов, а это уже не очень дружественно для обычного пользователя. Так что цвета для "эквалайзера" (ух, как же меня раздражает, когда так про спектроскоп говорят) обычно копировались из другой шкурки.

Меня, кстати, как-то товарищ попросил облегчить эту самую возню с цветами и я написал на Delphi программу для генерации палитр — в ней даже можно было в рамках набора цветов выбрать пару точек, указать их цвета, а точки между ними заполнить оттенками, чтобы получился градиент. Я даже научился делать градиенты сам — интернета у меня не было тогда, так что экспериментировал :) Да, градиенты в RGB — это сомнительная затея, сказал бы я нынешний себе тогдашнему, но заказчик мой остался доволен!

Ещё одна история из того времени вспоминается. Приличная доля дисков с "Дискографиями группы XYZ в MP3" в автозапуске содержала всё тот же Winamp с заготовленным плейлистом или какую-то программу-обоболочку, которая выводила обложки альбомов и тексты песен умела отображать, но играла музыку силами того же Winamp. Вот только этот Winamp при первом запуске молча переписывал на себя файловые ассоциации — да, вот этот вот Winamp на вашем приводе D: становился проигрывателем по умолчанию для всех медиа-файлов! И если диска из этой серии "дискографий" в приводе не было, то и музыку вы послушать не могли. Причём отучить "портативную" версию Winamp брать на себя слишком много было несложно, но авторы этих сборников просто не стали заморачиваться :) На таких дисках ещё и шкурка у WA была нестандартная, но всегда одна и та же "зелёненькая" — среди моих знакомых были даже ценители именно её.

Я в какой-то момент устал от того, что все эти дискографии настолько халтурно сделаны. И написал свою оболочку для дискографии "Алисы" — чёрное окно, красные буквы, всё как положено. Тексты песен показывала, музыку играла сама — силами WMPlayer component. Ещё и записал всю эту красоту на болванку из чёрного ИК-прозрачного пластика!

Что ни говори, Winamp — целое явление и пласт культуры. Авторы, правда, в какой-то момент свернули не туда. В том числе и усложнив модификацию внешнего вида, поскольку в интерфейсе появились всякие выдвигающиеся панели и само окно стало "резиновым". Так что культура выделки шкур потихоньку исчезла. Остались только очаги вроде XMMS на unix-системах.
🔥4👍2💩1
(Разделил публикацию на две, а то опять в одну Телеграм не захотел умещать. Читайте выше начало)​​

А ещё Winamp 2 жив в виде Webampоткрытой реализации большей части функций оригинала с помощью Web-технологий. Появился Webamp году в 2014, так что проект это достаточно взрослый. Даже визуализации музыки показывать умеет силами WebGL — да-да, тот самый MilkDrop, только прямо в браузере! И, конечно же, шкурки поддерживаются оригинальные, у проекта даже есть целый музей: Winamp Skin Museum — вот тут-то вы точно сможете найти ту самую вашу любимую шкурку с Сакурой, собирательницей карт или с Бредом Питтом в золоте. И мало того, что любой экспонат можно рассмотреть, так все они ещё и действующие, благодаря всё тому же Webamp!
🔥15👍1💩1