effers/README.org

144 lines
3.1 KiB
Org Mode
Raw Normal View History

2022-01-19 20:56:39 +00:00
* effers
2022-01-19 21:14:40 +00:00
effect handlers in rust
** 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 {
fn print(&mut self, s: &str);
}
trait Logger {
fn debug(&mut self, s: &str);
fn info(&mut self, s: &str);
}
2022-01-19 20:56:39 +00:00
#+end_src
2022-01-19 21:14:40 +00:00
all the trait functions (that are used in programs) must take ~&mut self~ as a parameter
*** defining a program
programs are defined as a normal function, with the added ~program~ attribute
2022-01-19 20:56:39 +00:00
#+begin_src rust
2022-01-19 21:14:40 +00:00
#[program(Smth => Printer(print as p), Logger(debug, info))]
fn smth(val: u8) -> u8 {
p("hey hi hello");
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-19 21:14:40 +00:00
the first token (~Smth~) will be the name of the program. effects are listed after the ~=>~ token
**** listing effects
effects are listed by writing the trait's name, followed by a parenthesized list of the functions that will be used
functions can be given an alias using the ~as~ keyword
*** defining effect handlers
effect handlers are defined by declaring a struct, and implementing the trait on it
#+begin_src rust
struct IoPrinter;
impl Printer for IoPrinter {
fn print(&mut self, s: &str) {
println!("{}", s)
}
}
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)
}
fn info(&mut self, s: &str) {
println!("info: {}", s)
}
}
#+end_src
2022-01-19 20:56:39 +00:00
2022-01-19 21:14:40 +00:00
*** running programs
programs are run by providing the corresponding handlers in order, 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
let result: u8 = Smth.add(IoPrinter).add(FileLogger).run(3);
assert_eq!(result, 6);
#+end_src
2022-01-19 20:56:39 +00:00
2022-01-19 21:14:40 +00:00
** full example
#+begin_src rust
use effers::program;
#[program(Smth => Printer(print as p), Logger(debug, info))]
fn smth(val: u8) -> u8 {
p("hey hi hello");
debug("this is a debug-level log");
info("this is a info-level log");
val + 3
}
fn main() {
// maybe smth like this?
let result: u8 = Smth.add(IoPrinter).add(FileLogger).run(3);
assert_eq!(result, 6);
let other_result: u8 = Smth
.add(IoPrinter)
.add(NetworkLogger {
credentials: "secret password".to_string(),
})
.run(8);
assert_eq!(other_result, 11);
}
// effects
trait Printer {
fn print(&mut self, s: &str);
}
trait Logger {
fn debug(&mut self, s: &str);
fn info(&mut self, s: &str);
}
struct IoPrinter;
impl Printer for IoPrinter {
fn print(&mut self, s: &str) {
println!("{}", s)
}
}
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)
}
fn info(&mut self, s: &str) {
println!("info: {}", s)
}
}
struct NetworkLogger {
credentials: String,
}
impl Logger for NetworkLogger {
fn debug(&mut self, s: &str) {
println!(
"debug through network: {}; with password {}",
s, self.credentials
)
}
fn info(&mut self, s: &str) {
println!(
"info through network: {}; with password {}",
s, self.credentials
)
}
}
#+end_src