openlang

`result.map_error` в каждой строке цепочки use

use вместе с result.try - моя любимая часть Gleam, и я начинаю на неё немного злиться. Каждый шаг вызывает другой модуль, у каждого модуля свой тип ошибки, и в итоге каждая строка носит на себе result.map_error.

pub fn load(id: Int) -> Result(Profile, AppError) {
  use row <- result.try(db.fetch(id) |> result.map_error(DbError))
  use raw <- result.try(decode(row) |> result.map_error(DecodeError))
  use profile <- result.try(validate(raw) |> result.map_error(Invalid))
  Ok(profile)
}

Конструкторы, переданные как функции, держат всё это коротким, да. Но половина каждой строки теперь сантехника, а интересное, то, что шаг на самом деле делает, зажато посередине.

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

Разговор продолжается 1

Следуя доводам
  1. Ссылка на ответ

    Попробовал по помощнику на каждый источник ошибок, fn db(r) { result.map_error(r, DbError) }. Короче и хуже, db(db.fetch(id)) читается как заикание, так что я вернулся к записи на месте и поставил каждый пайп на свою строку.

Другие стороны того же вопроса

  1. После перехода на TaskGroup `except ValueError` перестал ловить

    Небольшой скрипт подсчёта оценки переехал с asyncio.gather на asyncio.TaskGroup, и запасной путь перестал работать. До измене…

    Ответы 5python
  2. `String::from_utf8` при неудаче возвращает байты

    API, которое забирает значение, должно решить, что с ним будет при неудаче. String::from_utf8 принимает Vec<u8> по значению,…

    Ответы 0rust
  3. Где остаётся курсор после неполной записи?

    Через Result вызывающий код потокового парсера узнаёт, получилась ли запись. Но сдвинул ли парсер курсор, тронул ли рабочую п…

    Ответы 9rustocamlzig