Закладаюся, що більшість з вас не чула про мову Rye.
Я досі мрію, що для моєї улюбленої мови Red🔺 колись вийде повноцінний реліз. А допоки цього не трапилося (і насправді вже не трапиться), звертаю увагу на будь-що інше, де REBOL 💻 вказаний як джерело натхнення. І якщо Red — це буквально той самий REBOL з додатковими фічами, то Rye зроблений скоріше «за мотивами», хоча спільних рис достатньо.
По-перше, він так само гомоіконний: між даними та кодом немає жодної різниці — це все лише блоки слів, які набувають якогось конкретного значення в контексті. Але якщо в ліспах списки на кшталт
По-друге, у мові фактично нема якихось ключових слів або спеціальних конструкцій. Усі
Ну а ще виходить (по-третє), що можна створити контекст, в якому цих усіх функцій не буде взагалі, зате можна наповнити його власними штуками. Це активно використовується для створення діалектів. Останні є фактично eDSL, і вони дуже різноманітні, що як добре, так і погано з обʼєктивних причин.
Чисто з погляду на синтаксис Rye трохи сумнівний місцями. Не на мій смак. Трохи приємніше за ліспи, але досі гірше, ніж REBOL чи Red. Думаю, вся справа в дужках: в ліспах використовуються переважно круглі, і їх багато, тут же їх менше, але вони фігурні, а в REBOL дужки квадратні! Що це значить? Правильно — що не треба тиснути Shift! Оптимізація процесів😀
Ще є всілякі приколи, як можна записувати одні й ті самі слова по-різному:
Тулити щось прямо до дужок не можна — обовʼязково ставити пробіл. Хз, мені не дуже це подобається.
Тепер трохи про мінуси. Одним з помітних недоліків єте, що ніхєра не працює. Ну може не геть прям усе, але за той час, упродовж якого я намагався розвʼязати задачі, я бачив і функції, які працюють не так, як описано, і якісь внутрішні краші. Документації дуже мало, деяка взагалі застаріла. Врешті довелося плюнути на це діло й закрити третій день за допомогою 🆕 , яка дивним чином до речі схожа синтаксично, але звісно не настільки гнучка. (А четвертого дня — учора — взагалі розвʼязував задачі на 💻 . Кочуся потроху донизу).
Сам інтерпретатор до речі на🦶 написаний, що потенційно дозволяє легко кроскомпілювати програми під будь-які системи, але я не перевіряв.
У підсумку скажу, що лишився трохи розчарований. Чувак-автор — молодець, але видно, що йому бракує чи то наснаги, чи то часу, щоб стабілізувати й розвивати мову швидше. Навіть логотип ШІ-шний. Тож лишаємося ми й надалі без сучаснішого нащадка REBOL.
Я досі мрію, що для моєї улюбленої мови Red
По-перше, він так само гомоіконний: між даними та кодом немає жодної різниці — це все лише блоки слів, які набувають якогось конкретного значення в контексті. Але якщо в ліспах списки на кшталт
(+ 100 500) обчислюються одразу, хоча цьому можна запобігти додавши якийсь апостроф або ще щось залежно від діалекту, то в Rye (як і в REBOL) навпаки — нічого само по собі не обчислюється, а треба робити do { _+ 100 500 }.По-друге, у мові фактично нема якихось ключових слів або спеціальних конструкцій. Усі
if, for, while і ще купа усіляких — це звичайні функції, які приймають або скалярні значення, або ті ж блоки. Виходить, що той do зазвичай вже є десь усередині них, тож на практиці у своєму коді бачиш його не часто. Ну а ще виходить (по-третє), що можна створити контекст, в якому цих усіх функцій не буде взагалі, зате можна наповнити його власними штуками. Це активно використовується для створення діалектів. Останні є фактично eDSL, і вони дуже різноманітні, що як добре, так і погано з обʼєктивних причин.
Чисто з погляду на синтаксис Rye трохи сумнівний місцями. Не на мій смак. Трохи приємніше за ліспи, але досі гірше, ніж REBOL чи Red. Думаю, вся справа в дужках: в ліспах використовуються переважно круглі, і їх багато, тут же їх менше, але вони фігурні, а в REBOL дужки квадратні! Що це значить? Правильно — що не треба тиснути Shift! Оптимізація процесів
Ще є всілякі приколи, як можна записувати одні й ті самі слова по-різному:
add: pfn { a b } { a + b } ; pure btw!
div: pfn { a b } { a / b }
div ( add 3 9 ) 6 ; 2.000000
( 3 .add 9 ) .div 6 ; 2.000000
3 .add 9 |div 6 ; 2.000000Тулити щось прямо до дужок не можна — обовʼязково ставити пробіл. Хз, мені не дуже це подобається.
Тепер трохи про мінуси. Одним з помітних недоліків є
Сам інтерпретатор до речі на
У підсумку скажу, що лишився трохи розчарований. Чувак-автор — молодець, але видно, що йому бракує чи то наснаги, чи то часу, щоб стабілізувати й розвивати мову швидше. Навіть логотип ШІ-шний. Тож лишаємося ми й надалі без сучаснішого нащадка REBOL.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🤔3👀1
Враховуючи, що останні пару місяців я дуже багато займаюся тим, що перекладаю JSONʼи з місця на місце, колупаю CSV і тицяю патиком SQLite-базу, можу впевнено заявити: нічого краще за Nushell для цього ще не вигадали!
Усілякі там фільтрації, агрегації, щось звідкись дістати, транспонувати, перекрутити, згорнути список — це все робиться в декілька рядків легкого для сприйняття коду. Не треба вчити всратий синтаксис🙂 А потім хоч читайте та пишість JSON 💻 , хоч CSV, хоч TOML 💻 якийсь — вже без різниці.
Але інколи все ж буває зручніше зробити щось нашвидкоруч в UI. І якщо Excel вам для цього здається заважким, то я оце знайшов і спробував легшу прогу: SmoothCSV. Вона виявилася вельми непогана! Нічого надзвичайного, але під мій випадок вона якраз ідеальна. І там навіть є змога писати SQL-запити по CSV-шках, хоча я не пробував.
Усілякі там фільтрації, агрегації, щось звідкись дістати, транспонувати, перекрутити, згорнути список — це все робиться в декілька рядків легкого для сприйняття коду. Не треба вчити всратий синтаксис
jq, не треба писати скрипти на пайтоні, щоб перегнати один формат в інший — лише кілька одних і тих самих команд, і вуаля! З базових композитних типів там структури, списки й таблиці, причому останні еквівалентні першим, вкладеним у другі Але інколи все ж буває зручніше зробити щось нашвидкоруч в UI. І якщо Excel вам для цього здається заважким, то я оце знайшов і спробував легшу прогу: SmoothCSV. Вона виявилася вельми непогана! Нічого надзвичайного, але під мій випадок вона якраз ідеальна. І там навіть є змога писати SQL-запити по CSV-шках, хоча я не пробував.
Please open Telegram to view this post
VIEW IN TELEGRAM
Smoothcsv
SmoothCSV - The ultimate CSV editor for macOS & Windows
SmoothCSV is the ultimate CSV editor for macOS & Windows. It's fast, easy to use, and packed with powerful features.
❤8👍7👀1
2025 рік був складним у багатьох аспектах. Подекуди занадто складним. Але ми з вами досі тут, а це чогось та варте! Погляньмо на наші з вами результати в цифрах 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉31 12🥰6🍾4🔥3👍1🤨1👀1
Як ніби всіх труднощів 2025-го було недостатньо, цей рік ударив дуже сильно з самого початку.
Увечері третього січня наш найкращий у цілому світі кіт Осінь був вʼялуватий, тож я повіз його вночі до клініки, де його геть неочікувано для нас залишили під наглядом в стаціонарі з діагнозом діабетичного кетоацидозу. Виявилося, що він діабетик. А за кілька днів ми дізналися, що в нього ще й з серцем проблеми, які вдалося виявити лише на УЗД. І після майже тижня тяжкої боротьби за життя наш кіцюнька врешті пішов з цього світу.
Немає в жодній мові слів, достатніх описати весь відчай, біль і горе, які звалилися на нас з дружиною. Але ось вже місяць, як Осені нема. Перші тижні я був абсолютно недієздатний: не працював, передивився всі улюблені «добрі» фільми й серіали, які вже знаю напамʼять, зустрівся разок з друзями, пройшов разом з дружиною Зельду — словом, робив усе, аби дати психіці зачепитися хоч за щось знайоме, стабільне й бодай трохи позитивне. Тоді ми плакали перманентно, а зараз у середньому лише раз на день. Я хз, яка це вже спроба написати цей текст, але я знову плачу. Абсолютно все нагадує про Осінь: предмети, звуки, усі наші звички — все якось повʼязано з ним. Інколи дуже раптово накриває прям, бо здалося, що він увійшов до кімнати абощо. У ті моменти, коли він зазвичай спав, якось полегше. Хоча в цілому я можу стверджувати на 200%, що це найтяжчий період у моєму житті.
Окремо варто сказати, наскільки давить менталка. Украй складно позбутися тривоги, почуття провини, думок штибу «а треба було…», «а от якби ж я тільки…» тощо. Багато чого миттєво втратило сенс. Якісь покупки, котрим міг радіти ще декілька тижнів тому, зненацька стали настільки незначним дрібʼязком, що аж гидко від себе. Лише підтримка один одного допомагає. І, як не дивно, розповіді інших людей теж. Декілька друзів розповіли власні аналогічні історії з минулого, а дружина знайшла цілий сабреддіт, де люди щодня пишуть свої. Розуміння, що буквально в цю секунду тисячі інших людей по всьому світові відчувають те саме, трохи врівноважує.
⁂
Наш Осінь — найкращий кіт. Він найдобріший, дуже розумний і, як, певно, і всі орієнтали, — надзвичайно балакучий. Протягом девʼяти років (це так мало!) ми завжди були разом, навіть у подорожах. І загалом робили все можливе, щоб він був по-котячому щасливий, віддавали йому всю любов і турботу, на які спроможні. А він у відповідь обожнював і дружину, і мене — по-різному, але однаково сильно. І я думаю, що нам вдалося забезпечити йому чудове життя.
Сказати, що Осінь був моїм другом, — замало. Я переконаний, що він забрав у нас з дружиною по частині душі з собою, але нам для нього і не шкода. Бо він по собі не лишив порожнечу. Зараз досі невимовно болісно, і серце крається, але з часом це, мабуть, вщухне, і з нами лишиться його любов і памʼять про всі ті чудові моменти, які він нам подарував. Я дуже вдячний дружині, яка колись вибрала саме Осінь, другану, котрий допоміг його привезти, усім, хто нас підтримав, і загалом життю за наданий шанс прожити ці коротенькі девʼять років з найкращим у світі котом.
Отож тепер потроху повертатимуся до тями й почну, мабуть, знову писати сюди. Навряд чи часто, втім.
Увечері третього січня наш найкращий у цілому світі кіт Осінь був вʼялуватий, тож я повіз його вночі до клініки, де його геть неочікувано для нас залишили під наглядом в стаціонарі з діагнозом діабетичного кетоацидозу. Виявилося, що він діабетик. А за кілька днів ми дізналися, що в нього ще й з серцем проблеми, які вдалося виявити лише на УЗД. І після майже тижня тяжкої боротьби за життя наш кіцюнька врешті пішов з цього світу.
Немає в жодній мові слів, достатніх описати весь відчай, біль і горе, які звалилися на нас з дружиною. Але ось вже місяць, як Осені нема. Перші тижні я був абсолютно недієздатний: не працював, передивився всі улюблені «добрі» фільми й серіали, які вже знаю напамʼять, зустрівся разок з друзями, пройшов разом з дружиною Зельду — словом, робив усе, аби дати психіці зачепитися хоч за щось знайоме, стабільне й бодай трохи позитивне. Тоді ми плакали перманентно, а зараз у середньому лише раз на день. Я хз, яка це вже спроба написати цей текст, але я знову плачу. Абсолютно все нагадує про Осінь: предмети, звуки, усі наші звички — все якось повʼязано з ним. Інколи дуже раптово накриває прям, бо здалося, що він увійшов до кімнати абощо. У ті моменти, коли він зазвичай спав, якось полегше. Хоча в цілому я можу стверджувати на 200%, що це найтяжчий період у моєму житті.
Окремо варто сказати, наскільки давить менталка. Украй складно позбутися тривоги, почуття провини, думок штибу «а треба було…», «а от якби ж я тільки…» тощо. Багато чого миттєво втратило сенс. Якісь покупки, котрим міг радіти ще декілька тижнів тому, зненацька стали настільки незначним дрібʼязком, що аж гидко від себе. Лише підтримка один одного допомагає. І, як не дивно, розповіді інших людей теж. Декілька друзів розповіли власні аналогічні історії з минулого, а дружина знайшла цілий сабреддіт, де люди щодня пишуть свої. Розуміння, що буквально в цю секунду тисячі інших людей по всьому світові відчувають те саме, трохи врівноважує.
⁂
Наш Осінь — найкращий кіт. Він найдобріший, дуже розумний і, як, певно, і всі орієнтали, — надзвичайно балакучий. Протягом девʼяти років (це так мало!) ми завжди були разом, навіть у подорожах. І загалом робили все можливе, щоб він був по-котячому щасливий, віддавали йому всю любов і турботу, на які спроможні. А він у відповідь обожнював і дружину, і мене — по-різному, але однаково сильно. І я думаю, що нам вдалося забезпечити йому чудове життя.
Сказати, що Осінь був моїм другом, — замало. Я переконаний, що він забрав у нас з дружиною по частині душі з собою, але нам для нього і не шкода. Бо він по собі не лишив порожнечу. Зараз досі невимовно болісно, і серце крається, але з часом це, мабуть, вщухне, і з нами лишиться його любов і памʼять про всі ті чудові моменти, які він нам подарував. Я дуже вдячний дружині, яка колись вибрала саме Осінь, другану, котрий допоміг його привезти, усім, хто нас підтримав, і загалом життю за наданий шанс прожити ці коротенькі девʼять років з найкращим у світі котом.
Отож тепер потроху повертатимуся до тями й почну, мабуть, знову писати сюди. Навряд чи часто, втім.
Доволі важко писати після такої перерви й таких подій. Але насправді я багато прикольного дізнався й зробив за останній час у спробах відірватися від реалій, тож варто розповісти.
Наприклад, як і в будь-якого поважного айтівця, є в мене такий собі home lab. Ви-то всі кубернетіси та кластери крутите, я знаю, але мені вистачає Docker💻 + Tailscale 💠 .
І щоб не тільки в чорну консоль витріщатися, я користуюся Portainer: там можна і контейнерами керувати, логи там почитати абощо, підняти стек з компоуза, навіть є кривенький механізм деплоя через Git💻 .
Так ось того тижня я викинув його на звалище, бо поставив собі Dockhand. Абсолютно випадково натрапив, і він мені одразу припав до душі, бо зроблений якось… правильно… хз. Він банально зручніший у всьому. Відкриті сирці, звісно (якийсь поляк педалить: Bun, TypeScript, Svelte — норм). Підіймається на раз-два.
На VPS поставив собі агента (Hawser), щоб можна було віддалено керувати. Він до речі на🦶 написаний, тож можна прямо бінарем запускати без докера.
У Dockhand швидкий інтерфейс, усілякі приколи з переглядом логів одночасно з декількох контейнерів (типу як у Dozzle) тощо. А головне — значно зручніший GitOps, як на мене! Можна деплоїти купу всього з одного ґіт-сховища, як я й роблю, але при цьому не треба всюди окремо прописувати токени доступу — достатньо зробити це один раз. Ще він вміє о́брази на вразливості сканувати. Бекапів поки нема, але обіцяють найближчим часом додати. Ще б оце якось до нього 1Password прикрутити, щоб не палити паролі у змінних оточення. Треба глянути, наскільки складно буде підвайбкодити. А, ну й SSO налаштувати.
Отже, це рішення я прийняв дуже швидко: про Portainer можна забути — хоч якась радість серед усіх цих інфраструктурних питань.
Наприклад, як і в будь-якого поважного айтівця, є в мене такий собі home lab. Ви-то всі кубернетіси та кластери крутите, я знаю, але мені вистачає Docker
І щоб не тільки в чорну консоль витріщатися, я користуюся Portainer: там можна і контейнерами керувати, логи там почитати абощо, підняти стек з компоуза, навіть є кривенький механізм деплоя через Git
Так ось того тижня я викинув його на звалище, бо поставив собі Dockhand. Абсолютно випадково натрапив, і він мені одразу припав до душі, бо зроблений якось… правильно… хз. Він банально зручніший у всьому. Відкриті сирці, звісно (якийсь поляк педалить: Bun, TypeScript, Svelte — норм). Підіймається на раз-два.
На VPS поставив собі агента (Hawser), щоб можна було віддалено керувати. Він до речі на
У Dockhand швидкий інтерфейс, усілякі приколи з переглядом логів одночасно з декількох контейнерів (типу як у Dozzle) тощо. А головне — значно зручніший GitOps, як на мене! Можна деплоїти купу всього з одного ґіт-сховища, як я й роблю, але при цьому не треба всюди окремо прописувати токени доступу — достатньо зробити це один раз. Ще він вміє о́брази на вразливості сканувати. Бекапів поки нема, але обіцяють найближчим часом додати. Ще б оце якось до нього 1Password прикрутити, щоб не палити паролі у змінних оточення. Треба глянути, наскільки складно буде підвайбкодити. А, ну й SSO налаштувати.
Отже, це рішення я прийняв дуже швидко: про Portainer можна забути — хоч якась радість серед усіх цих інфраструктурних питань.
Please open Telegram to view this post
VIEW IN TELEGRAM
Dockhand
Dockhand - Modern Docker Management
A powerful, intuitive Docker platform for everyone. Real-time container management, Compose stacks, Git deployments, and SSO - all free.
🔥23👍3👀2👎1
Кореш підкинув блог чувака, що робив дуже крутецькі інтерактивні статті. Обожнюю такі й навіть трохи колекціоную. Шкода, що їх доволі важко й довго робити, тому мало хто цим займається. От і цей автор навіть намагався якось монетизувати своє хобі, та, видно, не вийшло — з кінця 2024 року вже нічого нового не публікував.
Мені до вподоби прийшлися зокрема статті про те, як влаштований механічний годинник, як працює GPS або як працюють лінзи в камерах. Дуже цікаво, детально й загалом круто.
Мені до вподоби прийшлися зокрема статті про те, як влаштований механічний годинник, як працює GPS або як працюють лінзи в камерах. Дуже цікаво, детально й загалом круто.
ciechanow.ski
Mechanical Watch – Bartosz Ciechanowski
Interactive article explaining how a mechanical watch works.
🔥30👍8👀4🥰3😭1
Сідаєш такий разом з ШІ-шкою за прогу на Go (мову, котру я навіть ніколи окремо не вчив, але доволі успішно використовую), витрачаєш дві години, і гоп — готова тула. Все стабільно працює, всі потрібні фічі, які запланував, один бінарь і навіть вбудований Web UI!
Сідаєш з ШІ-шкою й усім своїм багатолітнім досвідом за прогу на C++, просираєш чотири години… Результат: вдалося нарешті підключити сторонню лібу для парсингу KDL так, щоб вона зібралася без помилок. Вельми очевидно й прямолінійно все: Xmake качає з ґітгаба архів релізу, розпаковує, знаходить там
Потім, правда, виявилося, що бібліотека для всіх рядків використовує виключно
Щоправда… схоже, вони забули додати ще дещо. Наприклад, бодай якісь функції чи типи, які б з ним працювали‽!! Може
Доведеться, видно, рядки туди-сюди між типами ганяти. Яке щастя, що в Qt є
Враховуючи, що в моїй програмі все одно є вбудований рушій💻 , я, якщо чесно, вже думав, чи не буде легше просто там той 🤗 парсити 😆
І наостанок тримайте ще історію про🦶 . Треба було мені того тижня зробити одну хєрню, і єдина тулза для цього, котру я знайшов, була написана якимсь нонеймом на колінці 10 років тому якраз мовою Go в ґіт-сховищі на декілька зірок. Тільки версія під macOS з релізів у мене не запрацювала, бо, підозрюю, що вона досі 32-бітна може бути абощо. То я стягнув собі репозиторій, щоб зібрати власноруч. Не знаю, яка там версія компілятора чи бібліотек була 10 років тому в чувака, але в мене-то найсвіжіша! Запускаю 🙂
Треба зменшувати використання сі-плас-пластика & Go touch grass.
Сідаєш з ШІ-шкою й усім своїм багатолітнім досвідом за прогу на C++, просираєш чотири години… Результат: вдалося нарешті підключити сторонню лібу для парсингу KDL так, щоб вона зібралася без помилок. Вельми очевидно й прямолінійно все: Xmake качає з ґітгаба архів релізу, розпаковує, знаходить там
CMakeLists.txt, накладає на нього щойно написану латку, без котрої ніц не працювало, збирає CMakeʼом і вуаля — магія!Потім, правда, виявилося, що бібліотека для всіх рядків використовує виключно
std::u8string — такий новий сучасний тип для UTF-8 з C++20. Чудово, що в C++ нарешті його додали, бо як же без UTF-8 у 20-х роках. Щоправда… схоже, вони забули додати ще дещо. Наприклад, бодай якісь функції чи типи, які б з ним працювали‽!! Може
std::u8stringstream? Ні, для потоків є тільки спеціалізації для char та wchar_t, а тут char8_t — він того ж розміру, вирівнювання й знаку, що й unsigned char, але все-таки окремий. Ну може тоді хоча б std::ifstream/std::ofstream? Нє, теж ні. Файли нам читати-писати не треба, як я бачу, ок. Ну, принаймні std::filesystem::path з такого можна сконструювати.Доведеться, видно, рядки туди-сюди між типами ганяти. Яке щастя, що в Qt є
QString, який всередині використовує char16_t, але дозволяє конвертувати з або в std::string. А для конвертації між std::string та std::u8string є чудові стандартні функції з красномовними назвами std::mbrtoc8 та std::c8rtomb (пропонуйте ваші варіанти, що це може значити). Враховуючи, що в моїй програмі все одно є вбудований рушій
І наостанок тримайте ще історію про
go build і… нуль помилок. Усе працює Треба зменшувати використання сі-плас-плас
Please open Telegram to view this post
VIEW IN TELEGRAM
kdl.dev
The KDL Document Language
kdl is a document language, mostly based on SDLang, with xml-like semantics that looks like you're invoking a bunch of CLI commands!
👍21🔥4🥴2🤣2
Вирішив зібрати трохи статистики щодо того, скільки в мене часу на які проєкти йде. Колись користувався WakaTime, а потім якийсь час навіть CodeTime від Software.com, але вони всі грошей вимагають для повнішої аналітики, а мені воно не аж настільки треба.
То краще заселфхостити, еге ж? Поставив місяць тому Ziit: на вигляд дуже лаконічна штука, мені навіть трохи подобається. Але ресурсів споживає зовсім не лаконічно! Одна тільки Timescale DB на 200–300 МБ оперативки чого варта. Плюс є низка інших моментів, що дратують. По-перше, постійно розлоговує. Буквально щогодини або щось таке. Нафіга‽🤬 По-друге, доволі лімітований набір розширень для IDE. І по-третє, немає API-шки для експорту — за таке взагалі треба карати. Ну й наостанок не підтримує OIDC.
Отже, вирішив відмовлятися від Ziit, а натомість написати своє! Вчасно схаменувся, втім😅 Мав на думці ідею рахувати не тільки той час, котрий я безпосередньо пишу код, але й той, коли використовую ШІ-агентів, бо врешті це добрячий такий шматок на себе перетягнуло. Але як виявилося, WakaTime це вже підтримує.
Тож натомість я підняв собі Wakapi — сумісну альтернативу WakaTime з відкритими сирцями. Він звісно трохи кривенький (наприклад, я так і не зміг змінити собі часовий пояс в налаштуваннях через якусь помилку, тож пішов і виправив руками прямо в базі😂 ), але свою справу знає. Написаний на 🦶 , споживає 40 МБ оперативки у докер-контейнері, працює швидко, і навіть OIDC підтримує! Для Claude Code та OpenCode є окремі плагіни, які звітують в систему час під категорією «ai coding» — можна окремо фільтрувати. Для VS Code та майже будь-якого вашого улюбленого редактора теж є. Дані можна зберігати в Postgres, але мені й SQLite 🪶 вистачає.
Хоча насправді це дивно трохи. Я міркував, як це писав би я, і дійшов висновку, що використав би DuckDB🦆 (може й не тому, що прям треба, а чисто тому, що не було нагоди кудись його прикрутити досі). З іншого боку всі розширення для IDE шлють якесь «серцебиття» на сервак з купою додаткової інфи (назва проєкту, файлу, гілки, мова тощо) дуже часто, а в DuckDB інфа стовпчиками зберігається, а не рядками, бо це OLAP. Така вставка, певно, за швидкодією значно гірше за SQLite буде, ну а раз у ніколи статистику порахувати можна і зі «звичайної» OLTP. То я, мабуть, врешті складав би все в SQLite і з часом переганяв пачками в DuckDB, хз. Звучить як приклад надмірної інженерії. Якщо хтось тямить, як такі речі правильно робити, або якщо є де почитати про DuckDB для повних нубасів типу мене, то напишіть, плз, у коментарі чи шо.
То краще заселфхостити, еге ж? Поставив місяць тому Ziit: на вигляд дуже лаконічна штука, мені навіть трохи подобається. Але ресурсів споживає зовсім не лаконічно! Одна тільки Timescale DB на 200–300 МБ оперативки чого варта. Плюс є низка інших моментів, що дратують. По-перше, постійно розлоговує. Буквально щогодини або щось таке. Нафіга‽
Отже, вирішив відмовлятися від Ziit, а натомість написати своє! Вчасно схаменувся, втім
Тож натомість я підняв собі Wakapi — сумісну альтернативу WakaTime з відкритими сирцями. Він звісно трохи кривенький (наприклад, я так і не зміг змінити собі часовий пояс в налаштуваннях через якусь помилку, тож пішов і виправив руками прямо в базі
Хоча насправді це дивно трохи. Я міркував, як це писав би я, і дійшов висновку, що використав би DuckDB
Please open Telegram to view this post
VIEW IN TELEGRAM
wakapi.dev
Wakapi - Coding Statistics
Wakapi is an open-source tool that helps you keep track of the time you have spent coding on different projects in different programming languages and more. Ideal for statistics freaks and anyone else.
🔥10👍3🤷♂1
Засмутили ви мене того тижня — жодного коментаря 😢 Шо, ніхто не відстежує час, витрачений на проєкти? Ну то таке…
Сьогодні хотів знову зачепити тему роботи з «секретами» при розробці проєктів, а саме: з паролями, API-ключами, токенами тощо. Мені особисто дуже муляє око, коли вони у відкритому вигляді на диску лежать, навіть якщо цей файл не потрапляє в ґіт.
Ну, власне, тому я їх відкрито вже давно й не тримаю. Колись уже розповідав, як використовую 1Password для підписування комітів та роботи з Ansible💻 . А сьогодні хотів трохи написати про
Проблема з ними якраз і полягає в тому, що вони в ґіті не зберігаються. Тобто щоразу, як зробив чистий клон проєкту, треба цей файл руками створювати. Звісно, можна покласти
Тому нині мої
Вочевидь, тут нема жодних секретів, які не можна було б зберігати в системі контролю версій, бо значення змінних — це просто посилання на конкретні записи 1Password. До того ж не треба взагалі нічого міняти: зробив клон — і все одразу працює. Єдиний мінус полягає в тому, що тепер замість умовного
Я, звісно, махав це щоразу руками друкувати, тому використовую
А нещодавно дізнався про ще одну нову альтернативну фічу 1Password (наразі бета). Тепер вони дозволяють створювати різні оточення зі своїми наборами секретів прямо в їхній програмі. І потім такі оточення можна монтувати за певним шляхом як🙂 Замість того, щоб записувати ці всі секрети відкрито на диск, вони просто створюють іменований жолоб (pipe по-вашому): щойно хтось намагається прочитати звідти дані, 1Password просить вас авторизувати цей запит і передає значення прямо в програму! Ніби нічого складного, але доволі креативний розвʼязок до проблеми.
Переваги підходу в тому, що ви запускаєте всі свої тулзи як зазвичай — без жодних
Взагалі подобається, що 1Password не стоїть на місці й постійно розвивається. Але не подобається, що вони й так не дешеві, а скоро ще й піднімають вартість передплати🥲
Сьогодні хотів знову зачепити тему роботи з «секретами» при розробці проєктів, а саме: з паролями, API-ключами, токенами тощо. Мені особисто дуже муляє око, коли вони у відкритому вигляді на диску лежать, навіть якщо цей файл не потрапляє в ґіт.
Ну, власне, тому я їх відкрито вже давно й не тримаю. Колись уже розповідав, як використовую 1Password для підписування комітів та роботи з Ansible
.env-файли.Проблема з ними якраз і полягає в тому, що вони в ґіті не зберігаються. Тобто щоразу, як зробив чистий клон проєкту, треба цей файл руками створювати. Звісно, можна покласти
.env.example, в якому принаймні назви всіх змінних будуть, але спробуй ще згадай, де і як ти ті ключі та токени отримував. У мене їх десятки, всі з різними правами й скоупами, і я швидко починав у цьому губитися.Тому нині мої
.env на вигляд зазвичай приблизно отакі:GITHUB_TOKEN="op://Work/repo-name/wrxqfrltnqlzgako6zx6fjak6m/GITHUB_TOKEN"
TF_VAR_github_app_private_key="op://Work/repo-name/private key"
TF_VAR_crowdin_token="op://Work/repo-name/CROWDIN_PERSONAL_TOKEN/value"
TF_VAR_discord_webhook="op://Work/repo-name/DISCORD_WEBHOOK_URL/value"
TF_VAR_rclone_config="op://Work/repo-name/RCLONE_CONFIG/value"
Вочевидь, тут нема жодних секретів, які не можна було б зберігати в системі контролю версій, бо значення змінних — це просто посилання на конкретні записи 1Password. До того ж не треба взагалі нічого міняти: зробив клон — і все одразу працює. Єдиний мінус полягає в тому, що тепер замість умовного
terraform apply доводиться писатиop run --env-file=".env" -- terraform apply
Я, звісно, махав це щоразу руками друкувати, тому використовую
just, про який теж неодноразово вже згадував.А нещодавно дізнався про ще одну нову альтернативну фічу 1Password (наразі бета). Тепер вони дозволяють створювати різні оточення зі своїми наборами секретів прямо в їхній програмі. І потім такі оточення можна монтувати за певним шляхом як
.env-файл. Але! Файлу насправді нема Переваги підходу в тому, що ви запускаєте всі свої тулзи як зазвичай — без жодних
op run. А головний мінус для мене: наразі все ж не дуже зручно цим керувати. До того ж після клонування треба заходити й монтувати це оточення в потрібну теку. Тож для себе я вирішив лишитися на попередньому варіанті.Взагалі подобається, що 1Password не стоїть на місці й постійно розвивається. Але не подобається, що вони й так не дешеві, а скоро ще й піднімають вартість передплати
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍11🤷♂1
Сьогодні про корисне й актуальне.
З усіма цими вашими ШІ-агентами штибу клода й копайлота яка проблема? Вони полюбляють позапускати мутних команд у процесі дослідження або написання коду, і далеко не всі з них безпечні. Тож ви або сидите й кожну з них затверджуєте, або дозволяєте йому робити що завгодно (звісно ні).
Ну, або треба щось думати про ізоляцію. От якби закинути все потрібне в пісочницю, то можна було б не надто хвилюватися, що він там запускає — принаймні домашню теку вам не знесе.
Як сказав тут один мій товариш: «сендбоксити ж не складно»🧐 І якщо ви такі ж, як він, то шо я можу сказати… Вітаю! Я ось ніколи цього не робив, і мені складно.
На щастя, не так давно дізнався про існування
і вуаля!
Воно підіймає мікровіртуалку (так, не контейнер), монтує теку вашого проєкту за тим же шляхом(❗️ ) і навіть прописує 💻 git config! Ну й запускає сам Claude Code звісно, причому в режимі вседозволеності. (Щоправда, на початку автентифікуватися просить, тому, щоб руками це не робити, краще передавайте ключ через змінні оточення перед запуском).
Там, до речі, не тільки Claude Code є: той же OpenCode також присутній. А то й можна навіть кастомне щось собі зібрати.
Не бачу тільки згадок про підтримку лінукса🤔 Наче лише macOS 🍏 та Windows 🪟 .
З усіма цими вашими ШІ-агентами штибу клода й копайлота яка проблема? Вони полюбляють позапускати мутних команд у процесі дослідження або написання коду, і далеко не всі з них безпечні. Тож ви або сидите й кожну з них затверджуєте, або дозволяєте йому робити що завгодно (звісно ні).
Ну, або треба щось думати про ізоляцію. От якби закинути все потрібне в пісочницю, то можна було б не надто хвилюватися, що він там запускає — принаймні домашню теку вам не знесе.
Як сказав тут один мій товариш: «сендбоксити ж не складно»
На щастя, не так давно дізнався про існування
docker sandbox — і це штука, яка спрощує життя! Замість claude просто запускаєте у своєму сховищіdocker sandbox run claude
і вуаля!
Воно підіймає мікровіртуалку (так, не контейнер), монтує теку вашого проєкту за тим же шляхом(
Там, до речі, не тільки Claude Code є: той же OpenCode також присутній. А то й можна навіть кастомне щось собі зібрати.
Не бачу тільки згадок про підтримку лінукса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🤔5🔥3🤯2😭1
Пишу останні пару місяців на TypeScript. Доволі цікаво, як ця мова розвивалася. Якщо в тому ж Dart сіли й зробили нормальну й «звичну» типізацію, то в TS взяли JavaScript, який забагато всього дозволяє, і спробували це типізувати.
Зокрема, типізація там структурна. Тобто на відміну від C++ не треба наслідуватися від якихось конкретних типів — достатньо переконатися, що всі поля і їхні типи збігаються. Тому
працює без проблем. Ну й воно вміє там ті типи звужувати за потреби та ще багато чого робити.
Відповідно, щоб типізувати принаймні стандартну лібу💻 , типочкам довелося добряче спітніти. Проблема лише в тому, що відносно легко всі ці перевірки типів обійти: стратегічно розставлені ШІ-шкою 😂 Але я поки по-дідівськи цією мовою кодю — руками.
І робив оце функцію (React-компонент) для малювання певних даних у комірці таблиці. Вона очікує на вхід обʼєкт (рядок таблиці), з якого потім дістає ті дані з певних полів. Єдина проблема, що тип рядків може бути різним, бо воно до API підвʼязане. Дані там ті точно є, але поля не завжди називаються так, як треба. Вирішив зробити мапінг з одних на інші, щоб можна було писати щось типу:
і тоді всередині я очікую
«Але було б прикольно це типізувати, щоб не відстрелити собі ногу» — подумав я (бо після C++ ніг не так щоб багато лишилося). І це дійсно можна там зробити!
Тобто ми тут буквально пишемо, що маємо обʼєкт, ключі якого мають бути ключами
До речі, C++-програмістам, які JS ніколи не вчили, а просто почали його використовувати в якомусь QML, запис з квадратними дужками на місті ключів здаватиметься дивним. Але насправді це звичайна фіча JS, коли треба зробити обʼєкт з ключем, який представлений не рядковим літералом, а виразом. Тобто замість:
можна написати просто
Тому я завжди раджу книжки читати, навіть якщо здається, що мова не «основна».
Ну а щодо🕸 не дивно, що він здобув таку популярність врешті, бо писати React на чистому JS просто неможливо. Це повна дупа була б.
Зокрема, типізація там структурна. Тобто на відміну від C++ не треба наслідуватися від якихось конкретних типів — достатньо переконатися, що всі поля і їхні типи збігаються. Тому
type Foo = { a: string; b: number };
type Bar = { a: string; b: number };
const foo: Foo = { a: '42', b: 42 };
const bar: Bar = foo;працює без проблем. Ну й воно вміє там ті типи звужувати за потреби та ще багато чого робити.
Відповідно, щоб типізувати принаймні стандартну лібу
any та unknown ріжуть то все під корінь І робив оце функцію (React-компонент) для малювання певних даних у комірці таблиці. Вона очікує на вхід обʼєкт (рядок таблиці), з якого потім дістає ті дані з певних полів. Єдина проблема, що тип рядків може бути різним, бо воно до API підвʼязане. Дані там ті точно є, але поля не завжди називаються так, як треба. Вирішив зробити мапінг з одних на інші, щоб можна було писати щось типу:
type Params = { fieldA: number; fieldB: number } // те, шо мені треба
type Whatever = { megaFieldA: number; megaFieldB: number }; // якийсь інший тип
func(whateverObj, { fieldA: 'megaFieldA', fieldB: 'megaFieldB' });і тоді всередині я очікую
fieldA і fieldB, але діставатиму їх за іншими іменами.«Але було б прикольно це типізувати, щоб не відстрелити собі ногу» — подумав я (бо після C++ ніг не так щоб багато лишилося). І це дійсно можна там зробити!
type MyKeyMap<SourceType> = Partial<{
[K in keyof Params]: keyof SourceType;
}>;Тобто ми тут буквально пишемо, що маємо обʼєкт, ключі якого мають бути ключами
Params (з яким працює мій компонент), а значеннями — ключами SourceType (пофіг якого, бо це дженерік). Ну й Partial на всяк, щоб не обовʼязково було всі поля мапити, якщо імена збігаються. І компілятор такий чік-чік — перевірив. Тобто отой 'megaFieldA' вгорі може й виглядає як текстовий рядок, але по факту компілятор знає, що це назва поля в обʼєкті. Прикольно!До речі, C++-програмістам, які JS ніколи не вчили, а просто почали його використовувати в якомусь QML, запис з квадратними дужками на місті ключів здаватиметься дивним. Але насправді це звичайна фіча JS, коли треба зробити обʼєкт з ключем, який представлений не рядковим літералом, а виразом. Тобто замість:
let foo = {};
foo[someVal + 1] = 'blabla';можна написати просто
const foo = { [someVal + 1]: 'blabla' };Тому я завжди раджу книжки читати, навіть якщо здається, що мова не «основна».
Ну а щодо
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23 3💊1
Там позавчора нарешті затвердили новий стандарт C++26, тож усіх вітаю. Тепер звісно доведеться почекати ще років 3–5–7, доки його імплементують у компіляторах, і все ж.
Саттер каже, мовляв, це найпотужніший стандарт з часів C++11, тож дивитимуся потихеньку, що там цікавого додали. Сьогодні про одну з таких фічей мова.
Мені завжди подобалося, як в💻 (точніше SPARK) можна описувати перед- та постумови для функцій (приклад поцупив звідси):
Віднині в💻 теж можна буде так робити! Має бути щось на кшталт отакого:
Ну або уявімо, що треба перевірити значення, яке повертається, то буде щось отаке:
Таким чином кількість того, що в C++ можна писати між блоком параметрів функції та її тілом, небезпечно наближається до Ada🙂
Фіча зветься контрактами, якщо шо, і там окрім
Отже, загалом корисно на вигляд. Хоча спершу варто почитати правила, за якими ця фіча взаємодіє з іншими😉 На закуску тримайте приклад, як це виглядає в трохи реальнішому коді. Тут вам і концепти, і контракти, і
Саттер каже, мовляв, це найпотужніший стандарт з часів C++11, тож дивитимуся потихеньку, що там цікавого додали. Сьогодні про одну з таких фічей мова.
Мені завжди подобалося, як в
procedure Set_Speed (S : in out Speed_Knots; New_Value : Speed_Knots)
with
Pre => New_Value >= 0.0 and New_Value <= 1000.0,
Post => S = New_Value;
Віднині в
void set_speed(speed_knots & s, speed_knots new_value)
pre(new_value >= 0.0 && new_value <= 1000.0)
post(s == new_value);
Ну або уявімо, що треба перевірити значення, яке повертається, то буде щось отаке:
auto calculate(auto && val) post(r: is_valid(r));
Таким чином кількість того, що в C++ можна писати між блоком параметрів функції та її тілом, небезпечно наближається до Ada
Фіча зветься контрактами, якщо шо, і там окрім
pre та post ще додали так званий contract_assert. На вигляд наче звичайний assert, як і був, тільки тепер не сішний макрос, а прям інструкція самої мови. Можна користуватися всередині функцій, щоб додати обрисів очікуванням від коду.Отже, загалом корисно на вигляд. Хоча спершу варто почитати правила, за якими ця фіча взаємодіє з іншими
constexpr, і trailing return type, і structured binding. template <std::floating_point T>
constexpr auto normalize(std::array<T, 3> vector) noexcept -> std::array<T, 3>
pre(is_normalizable(vector))
post(vector: is_normalized(vector))
{
auto& [x, y, z]{vector};
const auto norm{std::hypot(x, y, z)};
x /= norm, y /= norm, z /= norm;
return vector;
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍5💊2😁1😱1🤪1
Cіпласпластик
Засмутили ви мене того тижня — жодного коментаря 😢 Шо, ніхто не відстежує час, витрачений на проєкти? Ну то таке… Сьогодні хотів знову зачепити тему роботи з «секретами» при розробці проєктів, а саме: з паролями, API-ключами, токенами тощо. Мені особисто…
Перезавантажив увечері комп, що я роблю вкрай рідко, запускаю зранку бекенд через Docker Compose… а останній висить і ніц не робить! Взагалі.
Я вже і кеші почистив, і докер перестановив — не допомагає. Хоча просто🤔 Покрутив ще туди-сюди,
Нарешті промайнула думка спробувати з іншим
Поміркував, що могло піти не так, і погляд упав на😐
Отже, здобув +5 XP. Наступив на ці граблі, набив собі гулю — аби вам не довелося.
Я вже і кеші почистив, і докер перестановив — не допомагає. Хоча просто
docker чомусь норм docker compose --help принаймні повідомлення показує, а docker compose config лише порожнечу й тишу. Нарешті промайнула думка спробувати з іншим
compose.yaml: створив новий майже порожній з Alpine, і о диво — спрацювало! Чого ж з моїм не працює?Поміркував, що могло піти не так, і погляд упав на
.env. Виявляється, що після ребуту 1Password не змонтував цей файл, як я очікував. Тож на диску лежить unix pipe, з якого Compose першим же ділом намагається читати, а туди ніхто не пише! Ну він і чекає Отже, здобув +5 XP. Наступив на ці граблі, набив собі гулю — аби вам не довелося.
Please open Telegram to view this post
VIEW IN TELEGRAM
1🤯21👍7🤣2 1
Думав написати про це ще минулої середи, але ви мені тоді точно не повірили би 😄
Отже, в C++ тепер є новий різновид циклів —🙂 Хочемо, ми, наприклад, написати функцію зі змінною кількістю аргументів, яка виводитиме значення в консоль:
Раніше довелось би писати щось отаке:
Ніби й зрозуміло, що🐝 Boost.Hana. А в C++11 взагалі колись писали отак:
Тобто типовий ФП-підхід, де список ділиться на
А тепер можна буде писати отак:
Усе це розгортається під час компіляції в щось на кшталт:
Працює
перетворюється на
Ну й ще багато чого можна робити звісно. Проте найкраще ця штука себе показує з новою рефлексією, про котру ще згодом напишу.
Отже, в C++ тепер є новий різновид циклів —
template for template <typename... Ts> void print_all(Ts... elems);
print_all("foo", 42, 'p', 3.14); // використання
Раніше довелось би писати щось отаке:
template <typename... Ts>
void print_all(Ts... elems)
{
(std::println("{}", elems), ...);
}
Ніби й зрозуміло, що
elems розпаковуються в пачку виразів, кожний з яких — це println, але читається не дуже. Тому знавці використовували би, мабуть, void print_all() {}
template <typename T, typename... Ts>
void print_all(T first, Ts... rest) {
std::cout << first << std::endl;
print_all(rest...);
}Тобто типовий ФП-підхід, де список ділиться на
head:[tail] й обходиться рекурсивно, доки не дійде до порожнього.А тепер можна буде писати отак:
template <typename... Ts>
void print_all(Ts... elems) {
template for (auto elem : {elems...}) {
std::println("{}", elem);
}
}
Усе це розгортається під час компіляції в щось на кшталт:
template <typename... Ts>
void print_all(Ts... elems) {
{
{
auto elem = elems...[0]; // така індексація,
// до речі, також
// нова фіча
std::println("{}", elem);
}
{
auto elem = elems...[1];
std::println("{}", elem);
}
{
auto elem = elems...[2];
std::println("{}", elem);
}
}
}
Працює
template for не лише з пачками типів, але й з будь-чим. Наприклад, звичайними масивами. Такvoid f() {
template for (constexpr int I : std::array{1, 2, 3}) {
static_assert(I < 4);
}
}перетворюється на
void f() {
{
constexpr auto&& __range = std::array{1, 2, 3};
constexpr auto __begin = __range.begin();
constexpr auto __expansion_size = __range.end() - __begin; // 3
{
constexpr int I = *(__begin + 0);
static_assert(I < 4);
}
{
constexpr int I = *(__begin + 1);
static_assert(I < 4);
}
{
constexpr int I = *(__begin + 2);
static_assert(I < 4);
}
}
}Ну й ще багато чого можна робити звісно. Проте найкраще ця штука себе показує з новою рефлексією, про котру ще згодом напишу.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥7👍5🤯2🔥1🤔1🤣1