这是一个冗长的例子,因为我无法进一步减少它.铁锈游乐场
use std::marker::PhantomData;
use std::ops::{Add, Sub, Mul, Div};
pub trait Scalar
: Sized + Copy + Add<Self, Output = Self> + Sub<Self, Output = Self> + Mul<Self, Output = Self> + Div<Self, Output = Self>
{}
impl Scalar for u32 {}
pub struct ScalarVal<T>(T) where T: Scalar;
pub trait Pixel: Sized {
type ScalarType: Scalar;
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Gray<BaseTypeP>
where BaseTypeP: Scalar
{
intensity: BaseTypeP,
}
impl<BaseTypeP> Pixel for Gray<BaseTypeP>
where BaseTypeP: Scalar
{
type …Run Code Online (Sandbox Code Playgroud) 该防锈参考说:
赋值或复合赋值表达式的左操作数是左值上下文,一元借用的单个操作数也是如此.
[...]
在左值上下文中使用右值时,会创建并使用临时的未命名左值.
这种左值促销显然适用于借款:
let ref_to_i32 = &27; // a temporary i32 variable with value 27 is created
Run Code Online (Sandbox Code Playgroud)
但它似乎不适用于任务(虽然引用说的是所有左值上下文,而不仅仅是借用):
27 = 28; // error[E0070]: invalid left-hand side expression
Run Code Online (Sandbox Code Playgroud)
E0070的错误描述未提及此右值促销.这是参考文献中的错误还是确实有某种方法可以通过赋值或复合赋值表达式触发rvalue促销?
还有第三种左值上下文,参考描述也不正确.只要存在带有a的模式,ref绑定到该模式的左值就是左值上下文.事实证明,促销适用于这种情况:
let ref x = 3; // works
Run Code Online (Sandbox Code Playgroud)
显然,促销只对(复合)作业不起作用?
我搜索了类型Sync,但不是Send,因为它通常看起来像一个特征是另一个特征的超集("每种类型实现Sync也实现Send").我发现了这个问题,但唯一真正的答案真的很复杂.
所以我想出了这段代码:
struct Foo(Rc<()>); // <-- private field
impl Foo {
fn my_clone(&mut self) -> Self { // <-- mutable borrow
Foo(self.0.clone())
}
}
Run Code Online (Sandbox Code Playgroud)
我知道,编译器不会自动实现Send,也Sync为我喜欢的类型; 但我感兴趣的是什么,我可以放心地手动实现.我认为:
它应该能够实现Sync:拥有一个不可变引用Foo不会让我们对它做任何事情(因为我们只能my_clone()通过mutable/exclusive引用调用).没有做任何事情,什么都不会出错,对吧?
它应该无法实现Send:我们可以Foo在主线程中克隆我们(在启动另一个线程之前)以获取第二个对象.现在两个对象共享一些内存(引用计数,存储在a中Cell<usize>).如果我现在可以将其中一个对象发送到另一个线程,则两个线程都拥有a的所有权Foo,引用相同的内存.因此,两个对象可以同时调用my_clone(),导致对引用计数(数据竞争)的同时,不同步,可变的访问.
这种推理是正确的还是我错过了什么?
该Arc<T>文件说:
impl<T> Sync for Arc<T> where T: Send + Sync + ?Sized
impl<T> Send for Arc<T> where T: Send + Sync + ?Sized
Run Code Online (Sandbox Code Playgroud)
一个Arc允许多个线程同时访问底层T经由一个不可变的参考&T.只要T不能以非同步方式修改,这是安全的&T.对于具有" 继承可变性 "(几乎所有类型)的所有类型都是如此,对于具有不同步的" 内部可变性 "(例如RefCell,......)的类型则是如此.
据我了解,Send此处不需要绑定.举例来说,我觉得分享我的一个实现人工型Sync,但不是Send在一个Arc很安全.
最后,&T本身也没有这个约束!在对文档Send和Sync我们发现:
impl<'a, T> Send for &'a T where T: Sync + ?Sized
impl<'a, T> Sync for &'a T where …Run Code Online (Sandbox Code Playgroud) downcast()Rust Box类型的方法要求调用站点拥有Box实例的完全所有权.似乎没有可以使用借用引用的等效项.是否有一个原因?是否有适用于借用实例的解决方法?
在Rust中,如何避免编写这些循环?代码采用向量并将三个相邻元素相乘到产品.因此,外部循环遍历可以形成一组三个的所有元素,并且内部循环执行乘法.
我认为,困难在于外循环的不完整迭代(从元素0到last - 3).此外,内环必须使用子范围.
有没有办法避免编写循环?
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut products = Vec::new();
for seq in 0..v.len() - 3 {
let mut product = 1;
for offset in 0..3 {
product *= v[seq + offset];
}
products.push(product);
}
Run Code Online (Sandbox Code Playgroud) 几乎没有任何编程语言的句法语法是规则的,因为它们允许任意深度嵌套的括号。Rust 也这样做:
let x = ((((()))));
Run Code Online (Sandbox Code Playgroud)
但 Rust 的句法语法至少是上下文无关的吗?如果不是,什么元素使语法与上下文相关?或者语法甚至是递归可枚举的,就像C++ 的句法语法一样?
我有一个迭代器,我想用一个很好的方法折叠它(比如说Iterator::sum):
let it = ...;
let sum = it.sum::<u64>();
Run Code Online (Sandbox Code Playgroud)
然后我注意到我还需要知道迭代器中元素的数量。我可以编写一个for循环并手动进行计数和求和,但这并不好,因为我必须更改可能很长的迭代器适配器链以及所有这些。此外,在我的真实代码中,我没有使用sum,而是使用更复杂的“折叠方法”,我不想复制该逻辑。
我有一个想法(ab)使用Iterator::inspect:
let it = ...;
let mut count = 0;
let sum = it.inspect(|_| count += 1).sum::<u64>();
Run Code Online (Sandbox Code Playgroud)
这是可行的,但它是巧合还是这种行为有保证?的文档inspect提到每个元素都会调用闭包,但也指出它主要用作调试工具。我不确定在生产代码中以这种方式使用它是否是一个好主意。
下面是mod文档给出的例子syn::parse。
enum Item {
Struct(ItemStruct),
Enum(ItemEnum),
}
struct ItemStruct {
struct_token: Token![struct],
ident: Ident,
brace_token: token::Brace,
fields: Punctuated<Field, Token![,]>,
}
impl Parse for Item {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![struct]) {
input.parse().map(Item::Struct) // <-- here
} else if lookahead.peek(Token![enum]) {
input.parse().map(Item::Enum) // <-- and here
} else {
Err(lookahead.error())
}
}
}
Run Code Online (Sandbox Code Playgroud)
是input.parse().map(Item::Struct)有效的普通 Rust 语法(看起来不是Item::Struct函数),还是库的一种特殊语法proc_macro?如果是后者,是否有proc_macro具体语法规则的文档?
我刚开始使用 Rust 并想知道:是 Rust 解释器吗?有了解释器,Rust 编译器就不需要在每次调用时都编译所有的源文件,而只会在代码发生变化时进行解释。这就是 JavaScript 和 Python 没有真正的编译时间的原因。
使用 Rust 进行增量编译,但大型项目仍然很慢。对于 Web IMO,使用 Rust 开发 GUI 将是一个福音。
rust ×10
iterator ×2
compilation ×1
generics ×1
grammar ×1
interpreter ×1
loops ×1
lvalue ×1
rvalue ×1
side-effects ×1