此代码定义了一个非常简单的特征,用于表示二叉树和实现该特征的结构:
pub trait BTree<T> {
fn all(&self) -> Option<(&Self, &Self, &T)>;
fn left(&self) -> Option<&Self>;
fn right(&self) -> Option<&Self>;
fn value(&self) -> Option<&T>;
}
pub struct MyBTree<T> {
opt: Option<Box<(MyBTree<T>, MyBTree<T>, T)>>,
}
impl<T> BTree<T> for MyBTree<T> {
fn all(&self) -> Option<(&Self, &Self, &T)> {
match self.opt {
None => None,
Some(ref tuple) => Some((&tuple.0, &tuple.1, &tuple.2)),
}
}
fn left(&self) -> Option<&Self> {
match self.all() {
None => None,
Some((left, _, _)) => Some(left),
}
}
fn right(&self) -> …Run Code Online (Sandbox Code Playgroud) 感谢 @francis-gagn\xc3\xa9 \对另一个问题的出色回答,我对方差的工作原理有了更清晰的了解。例如,包含引用的类型在其生命周期参数上是协变的,如下所示。
\n\nstruct Foo<\'a> (PhantomData<&\'a str>);\n\n/// Foo is covariant over its lifetime parameter\npub fn test_foo<\'a:\'b, \'b:\'c, \'c>() {\n let fa: Foo<\'a> = Foo(PhantomData);\n let fb: Foo<\'b> = Foo(PhantomData);\n let fc: Foo<\'c> = Foo(PhantomData);\n\n let v: Vec<Foo<\'b>> = vec![fa, fb]; // fc is not accepted\n}\nRun Code Online (Sandbox Code Playgroud)\n\n另一方面,接受引用(或包含引用的类型)的函数在其生命周期参数上是逆变的。
\n\nstruct Bar<\'a> (PhantomData<fn(&\'a str)>);\n\n/// Bar is contravariant over its lifetime parameter\npub fn test_bar<\'a:\'b, \'b:\'c, \'c>() {\n let ba: Bar<\'a> = Bar(PhantomData);\n let bb: Bar<\'b> = Bar(PhantomData);\n let bc: Bar<\'c> …Run Code Online (Sandbox Code Playgroud) 我有一个类型,Foo它的方法可能会“引发”相关类型的错误Foo::Err。
pub trait Foo {
type Err;
fn foo(&mut self) -> Result<(), Self::Err>;
}
Run Code Online (Sandbox Code Playgroud)
我有另一个特性,它Bar有一个方法来处理Foo. Bar可能会发出自己的错误(由关联类型指定Bar::Err),但也可能会遇到由Foo它正在处理的生成的错误。
我可以看到两种方法来做到这一点,但我不知道哪一种最适合 Rust。
第一个将结果嵌入到结果中:
pub trait Bar1 {
type Err;
fn bar<F: Foo>(&mut self, foo: F) -> Result<Result<F, F::Err>, Self::Err>;
}
Run Code Online (Sandbox Code Playgroud)
第二个将两种错误类型合并到一个专用的枚举中:
pub trait Bar2 {
type Err;
fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Choice<F::Err, Self::Err>>;
}
Run Code Online (Sandbox Code Playgroud)
第二个在语义上看起来更清晰,但为处理额外的枚举创建了一些障碍。
据我了解,x实现trait时Foo,以下两行应等效。
x.foo();
Foo::foo(&x);
Run Code Online (Sandbox Code Playgroud)
但是,我遇到的问题是编译器接受第一个,而拒绝第二个,并带有一个非常奇怪的错误消息。
与往常一样,此示例可在操场上找到。
考虑以下两个相关特征。
pub trait Bar<'a> {
type BarError: Into<MyError>;
fn bar(&self) -> Result<(), Self::BarError>;
}
pub trait Foo: for<'a> Bar<'a> {
type FooError: Into<MyError>;
fn foo(&self) -> Result<(), Self::FooError>
where
for<'a> <Self as Bar<'a>>::BarError: Into<<Self as Foo>::FooError>;
}
Run Code Online (Sandbox Code Playgroud)
这个示例有点复杂,但是我确实需要使用生命周期参数Bar,而我不能使用它Foo。作为结果:
Bar::BarError在Foo(实际上有类型无限多Bar<'_>::BarError),所以Foo必须有自己的FooError;foo方法中绑定的复杂特征将BarErrors 转换为FooErrors。现在,让我们来实现Bar,并Foo为具体的类型,例如 …
据我了解,在 Rust 中创建空指针的标准(仅?)方法是std::ptr::null.
但是,该函数声明如下。
pub const fn null<T>() -> *const T
Run Code Online (Sandbox Code Playgroud)
在此声明中,T隐式假定具有固定大小(否则,它将是T: ?Sized)。因此,无法与*const str或一起使用此功能*const [u32]。在操场上测试一下
是否有充分的理由排除未调整大小的类型?想要创建一个 null 有*const str什么问题?
我有一个网站; 我手动维护的一些页面,其他一些,我使用工具(主要是Shinx)生成.对于手动维护的页面,我想迁移到Jekyll.
所以我的想法是将我的整个网站复制到一个jekyll项目中,逐步将页面从静态HTML文件移动到jekyll管理的markdown文件,更容易维护.另一方面,生成的页面将不受影响地复制.
它工作得很好......除了Jekyll不复制以下划线开头的文件,我有很多:Sphinx用一个前导下划线(_static,_modules...)命名一些特殊目录,然后发布一些python代码,其中也使用前导下划线(例如 __init__.py).
我知道我可以使用该include指令_config.yml,并逐个添加我想保留的所有已知文件/目录.但我仍然冒险错过一些文件(特别是当我的发电机进化时).
我宁愿告诉Jekyll,对于每个生成的子目录,"这个目录应该按原样复制".这样可以防止它查看其中的每个文件以查看是否应该对其进行处理,因此任何以下划线开头的文件都会被盲目复制.
有没有办法做到这一点?我找不到任何......
我有一个参考struct Foo<'a>包装&'a str.我想HashMap用Foos作为键来填充.这是一段代码(在操场上打开):
use std::collections::HashMap;
#[derive(PartialEq, Eq, Hash)]
struct Foo<'a> {
txt: &'a str,
}
fn main() {
let a = "hello".to_string();
let a2 = Foo { txt: &a };
let b = "hello".to_string();
let b2 = Foo { txt: &b };
let mut hm = HashMap::<Foo, u32>::new();
hm.insert(a2, 42);
println!("=== {:?}", hm.get(&b2)); // prints Some(42)
println!("=== {:?}", hm.get_mut(&b2)); // prints Some(42)
{
let c = "hello".to_string();
let c2 = …Run Code Online (Sandbox Code Playgroud) 我有一个关联类型的特征:
pub trait Speak {
type Error;
fn speak(&self) -> Result<String, Self::Error>;
}
Run Code Online (Sandbox Code Playgroud)
该特征的实现:
#[derive(Default)]
pub struct Dog;
impl Speak for Dog {
type Error = ();
fn speak(&self) -> Result<String, Self::Error> {
Ok("woof".to_string())
}
}
Run Code Online (Sandbox Code Playgroud)
并且函数返回该实现的实例:
pub fn speaker() -> impl Speak {
Dog::default()
}
Run Code Online (Sandbox Code Playgroud)
我知道在这个例子中我只能Dog用作返回类型,但在我的实际代码中我必须使用impl Speak(上面的函数实际上是由宏生成的).
据我了解,该impl Trait符号让出这实际上返回具体类型编译器的身影,所以我希望下面的函数正确编译,因为speaker()回报Dog,并且Dog::Error是类型():
fn test() -> Result<String, ()> {
speaker().speak()
}
Run Code Online (Sandbox Code Playgroud)
相反,我收到以下错误:
error[E0308]: mismatched types
--> src/lib.rs:21:5
| …Run Code Online (Sandbox Code Playgroud) 拉斯特大部分图案由性状(捕获Iterator,From,Borrow,等)。
为什么像len/这样普遍的模式is_empty在标准库中没有相关特征?这会导致我无法预见的问题吗?被认为是无用的吗?或者只是没有人想到它(这似乎不太可能)?