Propane: an experimental generator syntax for Rust
众所周知,Rust的Generator一直没有稳定,主要原因是Generator仍然有许多设计上的问题没有明确,所以无船同志写了一个名字叫Propane的新crate,旨在nightly上实验性的探索Rust Generator未来语法的可能性。
Propane中文翻译:丙烷,无船同志取名向来看起来比较奇怪,不知道是否有其他用意
目前nightly的generator只能写成闭包的形式(官方称作generator literal),比如这样:
#![feature(generators, generator_trait)]
fn main() {
let mut generator = || {
yield 1;
return "foo"
};
}
如果你写成这样的话:
#![feature(generators, generator_trait)]
fn fake_generator() -> &'static str {
yield 1;
return "foo"
}
fn main() {
let mut generator = fake_generator;
}
编译器会报E0627 A yield expression was used outside of the generator literal.这个错。也就是目前的generator不支持以函数的方式写。
前面说了,generator很多语法没有稳定甚至不支持,主要原因还是很多设计理念没有明确,所以Propane这个库先迈出了第一步。
#![feature(generators, generator_trait, try_trait)]
#[propane::generator]
fn fizz_buzz() -> String {
for x in 1..101 {
match (x % 3 == 0, x % 5 == 0) {
(true, true) => yield String::from("FizzBuzz"),
(true, false) => yield String::from("Fizz"),
(false, true) => yield String::from("Buzz"),
(..) => yield x.to_string(),
}
}
}
fn main() {
let mut fizz_buzz = fizz_buzz();
assert_eq!(&fizz_buzz.next().unwrap()[..], "1");
assert_eq!(&fizz_buzz.next().unwrap()[..], "2");
assert_eq!(&fizz_buzz.next().unwrap()[..], "Fizz");
assert_eq!(&fizz_buzz.next().unwrap()[..], "4");
assert_eq!(&fizz_buzz.next().unwrap()[..], "Buzz");
assert_eq!(&fizz_buzz.next().unwrap()[..], "Fizz");
assert_eq!(&fizz_buzz.next().unwrap()[..], "7");
// yada yada yada
let mut fizz_buzz = fizz_buzz.skip(90);
assert_eq!(&fizz_buzz.next().unwrap()[..], "98");
assert_eq!(&fizz_buzz.next().unwrap()[..], "Fizz");
assert_eq!(&fizz_buzz.next().unwrap()[..], "Buzz");
assert!(fizz_buzz.next().is_none());
}
Propane提供了一个generator
宏,可以让我们以函数的方式写Generator。当然Propane的主要目的是为了验证两个主要的设计理念是否合理:
1) 默认返回Iterator;return关键字可以终止generator,但只支持返回()
; generator中的?
表达式的默认行为和普通函数有差别
用Propane的generator
宏标记的函数是一个返回impl Iterator
的生成器,生成器中依然可以使用return
关键字来终止,但是不能返回其他类型的值,只支持返回()
。
生成器中支持?
表达式,但是与普通函数中不同的是,如果生成器yield是一个Result
类型,当?
表达式碰到错误情况时会把错误yield出去,而不是return出去。然后在下一次resume直接退出生成器。
2) 不支持自引用(Self-referential)
async/await语法稳定的时候为了解决自引用的问题花了很大的心思设计Pin和Unpin等概念。如果Generator默认返回迭代器Iterator的话,我们依然会碰到了自引用的问题。因为Iterator::next
在1.0就稳定了,我们不可能再去修改它的API来让迭代器支持自引用。如果不考虑性能,目前最简单粗暴的方法是可以把Generator的每个state装箱到堆上。
当然如果我们不支持自引用,就可以让generator支持零开销(zero cost),而且无船同志也大胆的推测(hypothesis):也许我们确实不需要一个支持自引用的Generator。
最后,无船同志强调,这几个理念仅仅是实验性的,而且也有可能是一次失败的尝试。
以上是我了解完Propane之后结合无船的博客整理的文章,Propane的代码也很简洁,大家可以去Github查看。
来源我的博客文章:https://folyd.com/blog/rust-generator-experimental/
无船的博客文章:Propane: an experimental generator syntax for Rust
Rust GameDev 月报#12 - July 2020
链接:https://rust-gamedev.github.io/posts/newsletter-012
MeiliSearch 0.13版
MeiliSearch 是Rust写的一个类似 Algolia Search 的开源版搜索引擎。
链接:https://blog.meilisearch.com/whats-new-in-0-13-0/
Building Canrun: A statically typed logic programming library for Rust (part 1)
作者在用Rust写一个名叫Canrun的逻辑编程(logic programming)库,这是他这是这一系列连载博客的第一篇。
链接: https://esimmler.com/building-canrun-part-1/
Parallel stream processing with Rayon
作者写了一遍博客分享他使用Rayon的并发流式处理体验。
链接:https://morestina.net/blog/1432/parallel-stream-processing-with-rayon
-- From 日报小组 Folyd
社区学习交流平台订阅:
评论区
写评论moz裁员1/4
--
👇
bitbegin: 无船的博客上说 他在找工作 是啥回事?
Generator用意何在?Rust的Iterator和range本来就可以惰性,异步有async/await,不需要别扭的yield来yield去。
别的不敢说,
叫丙烷可能预示这个玩意儿随时可能炸掉。。
2333,总之大老牛逼——(破音)
无船的博客上说 他在找工作 是啥回事?