TGViewer
YeaHub Tech YeaHub Tech @yeahub_tech · 412 subscribers
Post #278 106
🔖 JavaScript vs Gleam: пишем Todo CLI

Создаём одинаковое приложение на двух языках и сравниваем подходы.


🔸 Что делаем

CLI-приложение с 4 командами:
- list — показать все задачи
- add — добавить задачу
- done — отметить выполненные
- clear — удалить все

Формат хранения:
[ ] заголовок задачи
[*] выполненная задача


🔸JavaScript: Setup

pnpm init


Node v20, ESM модули, без сторонних библиотек. Файл todo.mjs.

Добавить задачу:
async function addTodo(filePath, todoTitle) {
return await useTodoFile(filePath, async (fd) => {
fd.appendFile(`[ ] ${todoTitle}\n`)
})
}


Форматированный список:
async function formattedTodos(filePath) {
return await useTodoFile(filePath, async (fd) => {
const content = await fd.readFile('utf8')
return content
.split('\n')
.filter((title) => title)
.map((title, index) => {
const isDone = /^\[\*\]/.test(title)
const rawTitle = title.match(/^\[[\s*]\]\s(.+)/)?.[1]
return `${index + 1} ${isDone ? strikethrough(rawTitle) : rawTitle}`
})
.join('\n')
})
}


Отметить выполненной:
async function markDone(filePath, ids) {
return await useTodoFile(filePath, async (fd) => {
const content = await fd.readFile('utf8')
const lines = content.split('\n')
ids.forEach((id) => {
lines[id - 1] = lines[id - 1].replace(/^\[\s\]/, '[*]')
})
await fd.truncate()
await fd.writeFile(lines.join('\n'))
})
}


🔸 Gleam: Setup

gleam new gleam_todos
gleam add argv simplifile gleam_community_ansi


Добавить задачу:
pub fn add_todo(file_path: String, title: String) -> Result(Nil, Nil) {
simplifile.append(file_path, "[ ] " <> title <> "\n")
|> result.replace(Nil)
|> result.nil_error
}


Форматированный список:
pub fn formatted_todos(file_path: String) -> Result(String, Nil) {
simplifile.read(file_path)
|> result.map(split_to_lines)
|> result.map(format_todo_lines)
|> result.map(join_lines)
|> result.nil_error
}

fn format_todo_lines(lines: List(String)) -> List(String) {
list.index_map(lines, fn(line, index) {
case line {
"[ ] " <> rest -> int.to_string(index + 1) <> " " <> rest
"[*] " <> rest -> int.to_string(index + 1) <> " " <> ansi.strikethrough(rest)
_ -> line
}
})
}


Отметить выполненной:
pub fn mark_done(file_path: String, ids: List(Int)) -> Result(Nil, Nil) {
simplifile.read(file_path)
|> result.map(split_to_lines)
|> result.map(fn(lines) { mark_todo_done(lines, ids) })
|> result.map(join_lines)
|> result.try(fn(content) { simplifile.write(file_path, content) })
|> result.nil_error
}


🔸 Запуск

JavaScript:
node todo.mjs add "first todo"
node todo.mjs list


Gleam:
gleam run add "first todo"
gleam run list



Итог ⬇️

JavaScript:
- ✅ Знакомый синтаксис
- ✅ Нативная работа с файлами
- ❌ Многословный код
- ❌ Ручная обработка ошибок

Gleam:
- ✅ Чистый, лаконичный синтаксис
- ✅ Result для обработки ошибок
- ✅ Pattern matching вместо регулярок
- ✅ Pipes |> для цепочек операций
- ❌ Менее знакомый синтаксис

Автор предпочитает Gleam за красивый код, мощную обработку ошибок и простые зависимости.

Gleam код читается как описание того, что делает программа, а не как она это делает.


📎 Статья

🎙 Новости

📝 База вопросов
  • ❤ 1
More from @yeahub_tech
  1. Oct 9, 2026#Собес #pipeline #ci #stage 🤔 Что происходит при автоматической сборке feature-ветки на s…
  2. Oct 8, 2026#course #задачи #тесты 📚 JavaScript. A3 Задачи Задачи на программирования на языке JavaSc…
  3. Oct 7, 2026#course #начинающие 📚 Твой Golang Твой Golang — это идеальный старт для освоения языка. П…
  4. Oct 5, 2026🧑‍💻 Вопросы с собесов для Node.js Разработчика 1. Как использовать Service Workers для р…
  5. Oct 2, 2026#Собес #transaction #propagation #required 🤔 Что такое propagation у транзакций и какие т…
  6. Oct 1, 2026#book #book 📚 Библия C#. 6-е изд. Автор: Михаил Фленов Это настольная книга программиста,…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →