Skip to content

Commit

Permalink
Обновлены страницы Core, Base
Browse files Browse the repository at this point in the history
  • Loading branch information
dx3mod committed Nov 16, 2024
1 parent 864b73a commit 3d69c88
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 37 deletions.
143 changes: 109 additions & 34 deletions docs/libraries/core/base.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
---
outline: deep
---

# Base

[Base] — одна из самых популярных альтернатив стандартной библиотеке OCaml'а.
Она добавляет значительный функционал, исправляет проблемные места в дизайне,
а также добавляет больше полиморфных возможностей.

Ее использование в составе [Core](./index.md) полностью раскрывается в книге [RWO](https://dev.realworldocaml.org/).

#### Смотрите также
а также добавляет больше полиморфных возможностей посредством

- [Stdio](https://v3.ocaml.org/p/stdio/latest/doc/Stdio/index.html)
- [ppx_jane](https://github.com/janestreet/ppx_jane)
> [!INFO] Изучение
> Ее использование в составе [Core](./index.md) полностью раскрывается в книге [Real World OCaml](https://dev.realworldocaml.org/).
## Дизайн

Целью Base является быть *портативной заменой* оригинальной стандартной библиотеки,
из-за чего в ней недоступны некоторые I/O функции. Но при необходимости их можно вызвать через модуль `Stdlib`.
полностью скрывающая оригинальный API,
из-за чего в ней недоступны некоторые I/O функции. Но при необходимости их можно вызвать через модуль `Stdlib` (или старый вариант `Caml`).

Далее опишем особенности использования Base в сравнение с оригинальной Stdlib.

### Явный контроль ошибок

Expand All @@ -24,40 +27,112 @@
Но чтобы не быть совсем чопорным, в Base существуют функции-двойники, что возвращают эксепшен. Их можно отличить
по характерному суффиксу `_exn` в название функции.

Например:
```ocaml
utop # List.hd [];;
(* - : 'a option/2 = None *)
utop # List.hd_exn [];;
(* Exception: Failure "hd". *)
```

> [!NOTE] Backtrace recording
> В Base по-умолчанию **включён** [backtrace recording](../../recipes/backtrace-recording.md), в отличие от стандартной библиотек.
> Почему это так можно прочитать [тут](https://discuss.ocaml.org/t/why-isnt-ocaml-recording-bactrace-by-default/9915/4).
### Полиморфное сравнение
> [!NOTE] Пример функций-двойников
> ```ocaml
> utop # List.hd [];;
> (* - : 'a option/2 = None *)
>
> utop # List.hd_exn [];;
> (* Exception: Failure "hd". *)
> ```
Оригинальные операторы сравнения (`=`, `>`, ...) являются операторами *структурного* сравнения представления данных в во время исполнения, что не совсем то, что вы хотели бы.
> [!IMPORTANT] Backtrace recording
> В Base по-умолчанию **включён** [backtrace recording](../../recipes/backtrace-recording.md), в отличие от стандартной библиотек. Поэтому обильное использование исключений может замедлить ваш код.
>
> Почему это так сделано можно прочитать [тут](https://discuss.ocaml.org/t/why-isnt-ocaml-recording-bactrace-by-default/9915/4). Но очевидно, чтобы пользователь предпочитал
> монадический способ обработки ошибок.
Поэтому в Base операторы сравнения (глобально) работают только с `int`. Чтобы сравнивать другие типы
вы должны явно использовать соответствующую функцию модуля или оператор.
Также, конечно, можно делать unwrap (если вы знакомы с Rust, то вам знакомо это понятие), то есть
достать значение из контейнера, либо упасть с паникой (в случае OCaml'а — с исключением).
Пример:
```ocaml
utop # String.equal "привет" "privet";;
utop # String.("привет" = "privet");;
# Error "что-то пошло не так..." |> Result.ok_or_failwith;;
Exception: Failure "что-то пошло не так..."
```
В случае если необходим прям настоящий полиморфизм, то для этого есть модуль `Comparable`.

```ocaml
let max (type t) (module C : Comparable.S with type t = t) =
List.reduce ~f:(fun max_val x -> if C.(max_val < x) then x else max_val)
### Явный полиморфизм и модули

Base не рекомендует использовать полиморфные функции сравнения OCaml, которые непоследовательны и чреваты ошибками. Полиморфное сравнение скрыто по умолчанию, и на него нужно явно ссылаться из модуля `Poly`.

Для сравнения значений отличных значений от int предлагают использовать соответствующие функции
и операторы из модулей типа.
> [!NOTE] Пример со сравнением строк
> ```ocaml
> utop # String.equal "привет" "privet";;
> utop # String.("привет" = "privet");;
> ```
Если нам требуется полиморфное сравнение, то используйте соответствующий type module,
(как трейты или интерфейсы в других языках).
> [!NOTE] Пример полиморфной функции max3
> ```ocaml
> let max3 (type a) (module T : Comparable.S with type t = a) x y z =
> T.max x (T.max y z)
> ```
> ---
> ```ocaml
> # max3 (module Int) 3 9 4
> ```
В Base очень развито использование функтор для, например, генерации множество функций
из базового определения. Опять же та же идея, что с трейтами, интерфейсами, классами.
> [!NOTE] Пример использования функтор для автогенерации функций
> ```ocaml
> (* user.ml *)
>
> module T = struct
> type t = { name: string; age: int }
>
> let compare ua ub = Int.compare ua.age ub.age
> let sexp_of_t _ = failwith "..."
> end
>
> include Comparable.Make (T)
> ```
>
> :::details Сигнатура
> ```ocaml
> module User :
> sig
> module T : sig ... end
> val ( >= ) : T.t -> T.t -> bool
> val ( <= ) : T.t -> T.t -> bool
> val ( = ) : T.t -> T.t -> bool
> val ( > ) : T.t -> T.t -> bool
> val ( < ) : T.t -> T.t -> bool
> val ( <> ) : T.t -> T.t -> bool
> val equal : T.t -> T.t -> bool
> val compare : T.t -> T.t -> int
> val min : T.t -> T.t -> T.t
> val max : T.t -> T.t -> T.t
> val ascending : T.t -> T.t -> int
> val descending : T.t -> T.t -> int
> val between : T.t -> low:T.t -> high:T.t -> bool
> val clamp_exn : T.t -> min:T.t -> max:T.t -> T.t
> val clamp : T.t -> min:T.t -> max:T.t -> T.t Base__.Or_error.t
> type comparator_witness = Base.Comparable.Make(T).comparator_witness
> val comparator : (T.t, comparator_witness) Base.Comparator.t
> end
> ```
> :::
## Полезности
### Открытие Base для всего Dune-проекта
Взято из [основной статьи про Dune](../../tools/dune.md#открытие-модуля-для-всего-проекта).
```Dune
(env (_ (flags (:standard -open Base))))
```
## Синтаксические расширения
Данное решение позволяет не писать `open Base` в каждом файле вашего проекта.

### Синтаксические расширения

Благодаря `ppx_jane` можно автогенерировать функции для наших модулей.

Expand Down
1 change: 1 addition & 0 deletions docs/libraries/core/command.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ let () = Command_unix.run ~version:"1.0" ~build_info:"RWO" command

- [`Cmdliner`](../cli/cmdliner.md) &mdash; мощнейший комбайн для тех, кто понял как его использовать, для остальных это непонятное overengineering поделие от сумасшедших.
- [`Arg`](https://ocaml.org/manual/api/Arg.html) &mdash; для простых интерфейсов, где надо принять пару флагов, наиболее удачное решение.
- [`Cmdlang`](https://github.com/mbarbin/cmdlang) &mdash; declarative command-line parsing for OCaml
25 changes: 22 additions & 3 deletions docs/libraries/core/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# Альтернативная стандартная библиотека от Jane Street
# Стандартная библиотека с батарейками

[Core][Core] &mdash; это расширенная и дополненная версия [Base](./base.md), минимальной замены стандартной библиотеки от Jane Street.
[Core][Core] &mdash; это полноценная замена стандартной библиотеки со всеми возможными батарейками
от [Jane Street]. Составлена из разных "подбиблиотек", вроде [Base](./base.md), [Stdio](https://ocaml.org/p/stdio/latest).

```sh
$ opam show core
```

[Core]: https://opensource.janestreet.com/core/
> [!NOTE] Смотрите также
> - Используется [в Real World OCaml](https://dev.realworldocaml.org/) в качестве стандартной библиотеке;
> - Статью про [Base](./base.md) &mdash; фундамент для Core;
> [!INFO] Рекомендация
> Используйте исключительно для прикладного, не используйте её в библиотеках,
> ибо это очень тяжёлая зависимость.
> [!IMPORTANT] Размеры бинарника
> В Core очень много кода и всего этого, поэтому выходной бинарник с её использованием может вас
> очень удивить &mdash; старт начинается с десятка мегабайт.


[Core]: https://opensource.janestreet.com/core/
[Jane Street]: https://www.janestreet.com/

0 comments on commit 3d69c88

Please sign in to comment.