English 中文(简体)
Rust的拉齐序列生成
原标题:Lazy sequence generation in Rust

我怎么能创造其他何种语言,称之为“历史”或“遗传”功能?

在沙尔,我可以使用<代码>yield,如以下例子(从Alma s docs)到以不使用中间人名单的方式生成可操作的序列:

# a generator that yields items instead of returning a list
def firstn(n):
    num = 0
    while num < n:
        yield num
        num += 1

sum_of_first_n = sum(firstn(1000000))

在Rust,我怎么能做类似的事情?

最佳回答
问题回答

Rust does有发电机,但它们是高实验,目前无法稳定地在Rust。

Works in stable Rust 1.0 and above

rel=“noreferer”>处理你的具体例子。 您可使用<条形状糖>。

fn main() {
    let sum: u64 = (0..1_000_000).sum();
    println!("{}", sum)
}

What if Range didn t exist? We can create an iterator that models it!

struct MyRange {
    start: u64,
    end: u64,
}

impl MyRange {
    fn new(start: u64, end: u64) -> MyRange {
        MyRange {
            start: start,
            end: end,
        }
    }
}

impl Iterator for MyRange {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        if self.start == self.end {
            None
        } else {
            let result = Some(self.start);
            self.start += 1;
            result
        }
    }
}

fn main() {
    let sum: u64 = MyRange::new(0, 1_000_000).sum();
    println!("{}", sum)
}

这些口号相同,但比灰色版本更明确。 值得注意的是,斯堪的发电机为你跟踪国家。 选择明确性,因此我们必须建立自己的国家,并以人工更新。 重要部分是执行Iterator trait。 我们具体规定,电梯产生某种特定类型的数值(,type 项目 = u64),然后处理每一频率的升值以及如何告诉我们已经到了绝缘状态。

这个例子并不像使用通用物的实际<代码>Range那样强大,而是显示了如何做到这一点的榜样。

Works in nightly Rust

夜晚会:does的发电机,但它们是高实验性。 你们需要找到一些不稳定的特征来创造这种特征。 然而,它看见pretty靠近沙尔的例子,加上一些与Rust有关的内容:

// 1.43.0-nightly (2020-02-09 71c7e149e42cb0fc78a8)
#![feature(generators, generator_trait)]

use std::{
    ops::{Generator, GeneratorState},
    pin::Pin,
};

fn firstn(n: u64) -> impl Generator<Yield = u64, Return = ()> {
    move || {
        let mut num = 0;
        while num < n {
            yield num;
            num += 1;
        }
    }
}

A. 现有一切 Rust在探测器上运行,我们创建了一个适应器,把发电机变成一个发电机,以便在更广泛的生态系统中发挥作用。 d 我预计,这一改编者最终将出席标准图书馆:

struct GeneratorIteratorAdapter<G>(Pin<Box<G>>);

impl<G> GeneratorIteratorAdapter<G>
where
    G: Generator<Return = ()>,
{
    fn new(gen: G) -> Self {
        Self(Box::pin(gen))
    }
}

impl<G> Iterator for GeneratorIteratorAdapter<G>
where
    G: Generator<Return = ()>,
{
    type Item = G::Yield;

    fn next(&mut self) -> Option<Self::Item> {
        match self.0.as_mut().resume(()) {
            GeneratorState::Yielded(x) => Some(x),
            GeneratorState::Complete(_) => None,
        }
    }
}

我们现在可以这样做:

fn main() {
    let generator_iterator = GeneratorIteratorAdapter::new(firstn(1_000_000));
    let sum: u64 = generator_iterator.sum();
    println!("{}", sum);
}

令人感兴趣的是,它比执行<代码>Iterator的力量要小。 例如,激光器有size_hint,使电离层的消费者能够了解有多少元素。 这使得在进入集装箱时能够优化<代码> 集体。 发电机没有任何此类信息。

https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1340-2019-04-11”rel=“nofollow noreferer”>Rust 1.34 table, You have convenient <,按每个要素执行<>),但至少可以避免你界定另一个方向。

<https://doc.rust-lang.org/std/iter/fn. from_fn.html>rel=“nofollow noreferer”> From_fn 接受封闭FnMut()-> Options<T>,并多次要求其创建 Iterator<T>。 在pseudo-Python,def from_fn(f):而(val := f(f))并非无:产出 val

// -> Box<dyn std::iter::Iterator<Item=u64>> in Rust 2015
fn firstn(n: u64) -> impl std::iter::Iterator<Item = u64> {
    let mut num = 0;
    std::iter::from_fn(move || {
        let result;
        if num < n {
            result = Some(num);
            num += 1
        } else {
            result = None
        }
        result
    })
}

fn main() {
  let sum_of_first_n = firstn(1000000).sum::<u64>();
  println!("sum(0 to 999999): {}", sum_of_first_n);
}

另一种选择是:std:iter:successors。 这对你的种子价值具有更大的作用。 在pseudo-Python:deflements(seed, f):虽然种子不是:生产种子;种子= f(见d)

fn firstn(n: u64) -> impl std::iter::Iterator<Item = u64> {
    std::iter::successors(
        Some(0),
        move |&num| {
            let next = num + 1;
            if next < n {
                Some(next)
            } else {
                None
            }
        },
    )
}

但是,@Shepmaster s note也适用于这些用途。 (tldr:常常是手动的Iterators 提高了记忆效率)

令人感兴趣的是,它比执行<代码>Iterator的力量要小。 例如,激光器有size_hint,使电离器的消费者能够了解有多少元素。 这使得在进入集装箱时能够优化<代码> 集体。 发电机没有任何此类信息。

(说明:<代码>impl) 是Rust2018的特征。 See Edition Guide/a> forposition and

您可使用我的打字性Rustgenerator Library。 支持稳定的Rust:

#[macro_use]
extern crate generator;
use generator::{Generator, Gn};

fn firstn(n: usize) -> Generator< static, (), usize> {
    Gn::new_scoped(move |mut s| {
        let mut num = 0;
        while num < n {
            s.yield_(num);
            num += 1;
        }
        done!();
    })
}

fn main() {
    let sum_of_first_n: usize = firstn(1000000).sum();
    println!("sum ={}", sum_of_first_n);
}

或更简单地说:

let n = 100000;
let range = Gn::new_scoped(move |mut s| {
    let mut num = 0;
    while num < n {
        s.yield_(num);
        num += 1;
    }
    done!();
});

let sum: usize = range.sum();




相关问题
SML Lazy sort of int list using streams

The question 1 Streams and lazy evaluation (40 points) We know that comparison sorting requires at least O(n log n) comparisons where were are sorting n elements. Let’s say we only need the ...

Creating a compound iterator in F#

I m implementing a checkers-like game, and I need a sequence that enumerates all legal moves for a given configuration. I ve got the following function, directly translated from C#: seq { for y1 ...

How Are Lazy Sequences Implemented in Clojure?

I like Clojure. One thing that bothers me about the language is that I don t know how lazy sequences are implemented, or how they work. I know that lazy sequences only evaluate the items in the ...

Lazy Sequences that "Look Ahead" for Project Euler Problem 14

I m trying to solve Project Euler Problem 14 in a lazy way. Unfortunately, I may be trying to do the impossible: create a lazy sequence that is both lazy, yet also somehow looks ahead for values it ...

Recursive function causing a stack overflow

I am trying to write a simple sieve function to calculate prime numbers in clojure. I ve seen this question about writing an efficient sieve function, but I am not to that point yet. Right now I am ...

Iterator blocks in Clojure?

I am using clojure.contrib.sql to fetch some records from an SQLite database. (defn read-all-foo [] (with-connection *db* (with-query-results res ["select * from foo"] (into [] res)))) ...

热门标签