- Name:
effect-as-a-clause - Proposed by: @mominul @satvikpendem
- Original proposal (optional): (#14)
We want to propose the usage of the effect clause to achieve operation genericity, for example:
trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
effect
async;
fn read_to_string(&mut self, buf: &mut String) -> Result<usize>
effect
async
{ .. }
}
/// Function to read from the file into a string which may exhibit async or const effect
fn read_to_string(path: &str) -> io::Result<String>
effect
async, const
{
let mut string = String::new();
// We can be conditional over the context the function has been called from,
// only when the function declaration has the `effect` clause
if async || !async {
let mut file = File::open("foo.txt")?; // File implements Read
// Because `read_to_string` is also an `effect` function that may or may not exhibit
// async-ness par the declaration, we can use it on both contexts (async/sync)
// we are placing the condition on.
file.read_to_string(&mut string)?; // .await will be inferred.
} else { // must be const
// As the `read_to_string` doesn't exhibit const-ness, we'll need to handle it ourselves.
string = include_str!(path).to_string();
}
Ok(string)
}
/// A normal function
fn read() {
let data = read_to_string("hello.txt").unwrap();
}
/// A async function
async fn read() {
let data = read_to_string("hello.txt").await.unwrap();
}
/// A const function
const fn read() {
let data = read_to_string("hello.txt").unwrap();
}So in a nutshell, a function declaration with an effect clause is a special type of function that may or may not exhibit async or const behavior(effect) and it depends on the context of the function being called from and we can execute a different piece of code according to the context from the function was called from too (like the const_eval_select, resolves #6):
fn function() -> Result<()>
effect
async, const
{
// ...
if async {
// code for handling stuff asynchronously
} else if const {
// code for handling stuff `const`-way
else {
// code for handling stuff synchronously
}
// ...
}/// A trimmed-down version of the `std::Iterator` trait.
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn size_hint(&self) -> (usize, Option<usize>);
}
/// An adaptation of `Iterator::find` to a free-function
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
where
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool;pub trait Iterator {
type Item;
async fn next(&mut self) -> Option<Self::Item>;
fn size_hint(&self) -> (usize, Option<usize>);
}
pub async fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
where
I: Iterator<Item = T> + Sized,
P: async FnMut(&T) -> bool;pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>
effect async;
fn size_hint(&self) -> (usize, Option<usize>);
}
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
where
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool effect async;
effect
asyncpub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>
effect async, const;
fn size_hint(&self) -> (usize, Option<usize>);
}
pub fn find<I, T, P>(iter: &mut I, predicate: P) -> Option<T>
where
I: Iterator<Item = T> + Sized,
P: FnMut(&T) -> bool effect async, const;
effect
async, constWe can introduce maybe keyword instead of effect if it seems more appropriate terminology for the semantics described in this proposal.