我正在学习Rust,我决定制作一个主要的筛子程序。它的工作和性能与我的同类C程序相当。
我是生锈的新手,所以我想要一些关于我的代码的反馈。特别是,我的代码是否采用了正确的锈蚀样式?
我知道有一些改变使算法更快,但我更喜欢反馈锈蚀代码的样式。
use std::env;
use std::fs::File;
use std::io::{Write, BufWriter};
fn prime_sieve(n: usize, ofile: &String) -> u32 {
let f = File::create(ofile).expect("Unable to create file");
let mut f = BufWriter::new(f);
let mut prime_mask: Vec<bool> = vec![true;n];
prime_mask[0] = false;
prime_mask[1] = false;
let mut p = 2; // First prime number
let mut count = 0; // Total number of primes found
let mut i;
// Main sieve loop
while p<n {
if prime_mask[p] {
f.write_all(format!("{}\n",p).as_bytes())
.expect("Unable to write to file");
count+=1;
i=2*p;
while i<n {
prime_mask[i] = false;
i += p;
}
}
p+=1;
}
count
}
fn main() {
let args: Vec<String> = env::args().collect();
let n: usize = args[1]
.trim()
.parse()
.expect("Wanted a number");
let ofile = &args[2];
let np = prime_sieve(n,ofile);
println!("Found {} primes less than {}. Wrote to {}", np, n, &args[2]);
}发布于 2017-03-20 13:36:08
;声明中的Vec之后。- vec;+ vec;&String,拿一个&str相反,。prime_mask的类型,推断可以处理它。i。for循环替换。请注意,这消除了代码中的可更改性。write!而不是分配一个String并编写它。writeln!而不是自己指定换行符,args向量的内部类型。使用_可以让编译器推断它。prime_sieve函数中,而是接受任何实现Write的类型。让测试变得更容易。use std::env;
use std::fs::File;
use std::io::{Write, BufWriter};
fn prime_sieve<W>(max_number_to_check: usize, mut output: W) -> u32
where W: Write
{
let mut prime_mask = vec![true; max_number_to_check];
prime_mask[0] = false;
prime_mask[1] = false;
let mut total_primes_found = 0;
const FIRST_PRIME_NUMBER: usize = 2;
for p in FIRST_PRIME_NUMBER..max_number_to_check {
if prime_mask[p] {
writeln!(output, "{}", p).expect("Unable to write to file");
total_primes_found += 1;
let mut i = 2 * p;
while i < max_number_to_check {
prime_mask[i] = false;
i += p;
}
}
}
total_primes_found
}
fn main() {
let args: Vec<_> = env::args().collect();
let n: usize = args[1].trim().parse().expect("Wanted a number");
let ofile = &args[2];
let f = File::create(ofile).expect("Unable to create file");
let f = BufWriter::new(f);
let np = prime_sieve(n, f);
println!("Found {} primes less than {}. Wrote to {}", np, n, ofile);
}对于您的使用,Vec<bool>会浪费空间。每个bool是一个字节,您使用的是一个字节。相反,有高效的位向量箱将数据打包得更紧密。
在将自文档添加到程序中时显式地放入类型难道没有好处吗?我来自Haskell,它还推断了类型,但鼓励显式类型签名。
在Rust中需要显式类型签名;不能推断函数的参数或返回类型。铁锈是从Haskell这里学到的,并且避免了如果你不提供签名的话,在很远的地方会发生惊悚行为的问题。
函数内部的推理是非常惯用的。有时您需要显式(例如集合类型到collect ),但除此之外,我不愿列出任何类型。
我有一种感觉,随着你习惯于锈蚀,这是一种改变。初学者更可能分散类型,然后学习信任和依赖推理。
如果存在歧义,那么改进变量名可能会有所帮助。例如,对我来说,“掩码”是一个整数,它使用按位运算对另一个整数应用。我不希望它是一个Vec。
我还使用了高度动态的语言,比如Ruby,在那里没有静态类型,所以函数中缺少类型并不过分。
对于
Vec<bool>类型,它们总是浪费空间吗?是否存在使用它们而不是位-vec类型的情况?
每个数据结构都有权衡。我知道的主要问题是,位向量不允许您获得对特定布尔值的引用,因为布尔值实际上并不存在。
https://codereview.stackexchange.com/questions/158274
复制相似问题