effers/README.org

108 lines
3.2 KiB
Org Mode
Raw Normal View History

2022-01-19 20:56:39 +00:00
* effers
2022-01-21 13:16:03 +00:00
ergonomic effect handlers in rust
2022-01-19 21:14:40 +00:00
** how to use
*** defining effects
effects are defined with traits
2022-01-19 20:56:39 +00:00
#+begin_src rust
2022-01-19 21:14:40 +00:00
trait Printer {
2022-01-21 13:16:03 +00:00
fn print(&self, s: &str);
fn available() -> bool;
2022-01-19 21:14:40 +00:00
}
trait Logger {
fn debug(&mut self, s: &str);
2022-01-21 13:16:03 +00:00
fn info(self, s: &str);
2022-01-19 21:14:40 +00:00
}
2022-01-19 20:56:39 +00:00
#+end_src
2022-01-21 13:16:03 +00:00
functions can take ~self~, ~&self~, ~&mut self~, or no ~self~ parameter. at this point ~self~ parameters with a specified type (like ~self: Box<Self>~) are not supported
2022-01-19 21:14:40 +00:00
*** defining a program
2022-01-21 13:16:03 +00:00
programs are defined as a normal function, with the added ~program~ attribute, which specifies (optional) a name for the program, and (required) the list of effects and corresponding functions that are used
2022-01-19 20:56:39 +00:00
#+begin_src rust
2022-01-21 13:16:03 +00:00
#[effers::program(MyCoolProgram =>
Printer(print(&self) as p, available as printer_available),
Logger(debug(&mut self), info(self))
)]
fn my_program(val: u8) -> u8 {
if printer_available() {
p("hey hi hello");
}
2022-01-19 21:14:40 +00:00
debug("this is a debug-level log");
info("this is a info-level log");
val + 3
}
2022-01-19 20:56:39 +00:00
#+end_src
2022-01-21 13:16:03 +00:00
**** name
the first token (~MyCoolProgram~) will be the name of the program. this is optional, and can be skipped:
#+begin_src rust
#[program(
Printer(print(&self) as p, available as printer_available),
Logger(debug(&mut self), info(self))
)]
#+end_src
if skipped, the default name will be the program function's name (~my_program~) in PascalCase (~MyProgram~)
2022-01-19 21:14:40 +00:00
**** listing effects
effects are listed by writing the trait's name, followed by a parenthesized list of the functions that will be used
2022-01-21 13:16:03 +00:00
***** listing effect functions
due to limitations of proc-macros, it's unknown what kind of ~self~ parameter the function takes, if any, and so it has to be explicitly specified (if you have ideas on how to fix this, please open a PR!): here's how each type is specified:
- ~fn print();~: ~print~
- ~fn print(self);~: ~print(self)~
- ~fn print(mut self);~: ~print(self)~
- ~fn print(&self);~: ~print(&self)~
- ~fn print(&mut self);~: ~print(&mut self)~
***** effect function aliases
functions can be given an alias using the ~as~ keyword (~print(&self) as p~) so that the function can be called by a different name inside the program
2022-01-19 21:14:40 +00:00
*** defining effect handlers
2022-01-21 13:16:03 +00:00
effect handlers are defined by declaring a struct, and implementing the corresponding trait on it
2022-01-19 21:14:40 +00:00
#+begin_src rust
struct IoPrinter;
impl Printer for IoPrinter {
2022-01-21 13:16:03 +00:00
fn print(&self, s: &str) {
2022-01-19 21:14:40 +00:00
println!("{}", s)
}
2022-01-21 13:16:03 +00:00
fn available() -> bool {
true
}
2022-01-19 21:14:40 +00:00
}
2022-01-19 20:56:39 +00:00
2022-01-19 21:14:40 +00:00
struct FileLogger;
impl Logger for FileLogger {
fn debug(&mut self, s: &str) {
println!("debug: {}", s)
}
2022-01-21 13:16:03 +00:00
fn info(self, s: &str) {
2022-01-19 21:14:40 +00:00
println!("info: {}", s)
}
}
#+end_src
2022-01-19 20:56:39 +00:00
2022-01-19 21:14:40 +00:00
*** running programs
2022-01-21 13:16:03 +00:00
programs are run by providing the corresponding handlers *in the order listed in the program definition*, and finally calling the ~run~ method, providing it the required parameters
2022-01-19 20:56:39 +00:00
2022-01-19 21:14:40 +00:00
#+begin_src rust
2022-01-21 13:16:03 +00:00
let result: u8 = MyCoolProgram.add(IoPrinter).add(FileLogger).run(3);
2022-01-19 21:14:40 +00:00
assert_eq!(result, 6);
#+end_src
2022-01-19 20:56:39 +00:00
2022-01-21 13:16:03 +00:00
** examples
- [[./examples/main.rs][main: general use case]]
- [[./examples/clone.rs][clone: how cloning and copying programs works]]
- [[./examples/module.rs][module: effects from other modules are supported]]