__| __|
| \__ \
_)_| ____/ //~\
// ~~\\
_ /─── ~~ \\
/ \ ─── ~~ ~~\
/ ~~\\ / ~~~ \
// ~~\\\ ~\ / ~~~ ~~\\
// ~~~ \~─~──── ~~ ~~~~~
~──// ~~~
───────╮ ~~~~ ~ ~ ~ ~~~~~~~ ~~~~~~~~~~~~~
# # │╮ ~~~~~~~~~~~~│ '│╭──── ╭─ ╭^^^^^^^^^
│╯ │` │ ╰╮───╯ ╭──╯ │ @ @ @ @
# #╭╮│╮ ╭╯ │ ╭───╯ ╭───┼─────────
╭─╰╯──^^╮ │` │. │──╯ │
╭─╰───────╯^╮───────│ │ '│ ╭─│ # # # #
────────╮@ @ │──╮ │ ..│ ╰─│
│ │ ╰───╭╯ ╭╯ │
# # # #│@ @ │ │ ╰─╮ '│ ╭─│ # # # #
│────╯ '│` │ . ╰╮ │ ╰─│
# # # #│ │ │ │ │
│ ╭╯ . ╰╮ ╭─│ # # # #
# # # #│ '│` ╭──╯ . ╰╮ ╰─│
│ │ │ . │ │
Overview
yerevan.rs is a Proof Of Concept (PoC) Rust library of Computation Expressions (CEs), aka "do-notations" in Haskell, inspired by F#'s CEs, but with changes and improvements in syntax-design.
- This package is a PoC of the idea that CEs could be very useful in Rust.
- The goal of this PoC is to evolve to a CEs feature proposal in Rust language, if it succeeds.
Why is this package only a PoC and not a solid solution?
- This package's implementation of CEs uses Rust macros, which slow the Rust compiler down. Besides, CEs are meant to be used often, which will significantly increase compilation time.
- Some syntax features of classical do-notations and CEs are not possible with Rust's
macro_rules.
Docs
- Firstly define the struct which is implementing all the neccessary functions for yerevan.rs's computation expressions. Like this:
- And then use your struct as computation expression type in
yer!macro. Like this:
yer!
Expressions
-
$your_struct =>defines the struct as the provider of computation expression functions. -
let! $your_var = $your_expressionuses the last defined struct in macros as the provider ofbindfunction and calls the$that_struct::bind($your_expression, &\|$your_var\| { next code })expression. -
let $your_var = $your_expressiondefines the variable$your_var. -
do! $your_expressionuses the last defined struct in macros as the provider ofbindfunction and calls the$that_struct::bind($your_expression, &\|_\| { next code })expression. -
do $your_expressionsimply runs$your_expression. -
ret! $your_expressionuses the last defined struct in macros as the provider ofret_fromfunction and calls the$that_struct::ret_from($your_expression)expression. -
ret $your_expressionuses the last defined struct in macros as the provider ofretfunction and calls the$that_struct::ret($your_expression)expression. -
yield $your_expressionuses the last defined struct in macros as the provider ofcombineandret_yieldfunctions and calls the$that_struct::combine(yer!($that_struct => next code, $that_struct::ret_yield($your_expression))expression. -
yield! $your_expressionworks the same asyieldbut uses$your_struct::ret_yield_frominstead ofret_yield. -
If-branching:
if else if else
// or
if else zero;
— Uses Rust's if-statement as an expression where $body is wrapped by yer! macro, and $your_struct::zero() for else case.
-
run $your_struct =>uses$your_struct::runfunction by providing last returned value from the CE as an argument for that function. -
$your_struct >>is the same asrunkeyword.
Examples
For now examples are available in /tests directory in repository. GH-link: https://github.com/marat0n/yerevan.rs/blob/dev/tests/common.rs
Roadmap (+ mini changelog)
The linked ones are done, they are linked to the crates.io/crates/yerevan page to the version where this roadmap-point was done. Not linked points are the plan for future updates.
- 0.1
yer!macro:some_struct =>expression to create the specified structure context where all next expressions of that CE will be executed using methods of this structure (in FP that kind of structures are called monads);let!expression executed bybind<T, U>: (val: T, fn: (T) -> U) -> Umethod in your defined struct (monad);letexpression (just define what you want without breaking the CE);do!expression executed the same aslet!but returned value frombindmethod is ignored;doexpression (just do what you want without breaking the CE);ret!expression executed byret_from<T>: (val: T) -> Tmethod in your defined struct (monad);retexpression executed byret<T, W<T>>: (val: T) -> W<T>method in your defined struct (monad);yieldexpression executed bycombine<T, W<T>>: (val1: W<T>, val2: T) -> W<T>whereval1-parameter is used for all next code in CE andval2-parameter is used for executingret_yield<T, U>: (val: T) -> U.
- initial tests, examples, docs.
- 0.2
- upgrade
yer!macro:- add implentation for methods:
Run,YieldFrom,Zerofrom F#'s CE-types; - add expressions to macro:
yeild!,if ... else.
- add implentation for methods:
- create default CEs for Option and Result types (Railway Execution type).
- upgrade
- 0.3
- upgrade
yer!macro:- add loop-expressions to macro:
for,while,loop.
- add loop-expressions to macro:
- upgrade
- 0.4
- upgrade
yer!macro:- add match-expression to macro.
- upgrade
- 0.5
- add more interesting and usefull CEs.