我正在用 Rust 开发一个单词生成器。该应用程序由两个主要结构组成:Letter和Alphabet.
Letter 由单个字符和有关其与其他字母关系的规则组成。
Alphabet包含元音和辅音的向量以及引用这些向量中字母的哈希图。这样做是为了可以在 O(1) 时间内检索字母的规则。
我创建了一个工厂方法来从 json 字符串(下面的代码)中读取字母表,但是我收到一个错误,指出字母表实例的寿命不够长。
src/word_generator/alphabet.rs:47:6: 47:14 错误:
alphabet寿命不够长 src/word_generator/alphabet.rs:47alphabet.add_letter(letter);src/word_generator/alphabet.rs:26:40: 55:3 注意:参考必须对 26:39 在块上定义的匿名生命周期 #1 有效... src/word_generator/alphabet.rs:26 pub fn from_json (json: &str)->字母{
注意:...但借用的值仅对 40:37 src/word_generator/alphabet.rs:40 处的语句 3 后面的块后缀有效 let mut episode = Alphabet::new(); src/word_generator/alphabet.rs:41
我理解错误(我希望),但我不明白它为什么会发生。为什么Alphabet函数返回的 实例new()被变量借用了alphabet?这不是移动操作吗?
pub struct Alphabet<'a>{
pub vowels: Vec<Letter>,
pub consonants: Vec<Letter>,
letters: HashMap<char,&'a Letter>
}
impl<'a> Alphabet<'a>{
pub fn new()->Alphabet<'a>{
return Alphabet{
vowels: Vec::new(),
consonants: Vec::new(),
letters: …Run Code Online (Sandbox Code Playgroud) 我有两个结构.App和Item.
我想要实现的是通过将可变引用传递给s构造函数来在结构Item的items向量中存储.AppItem
pub struct App<'a> {
items: Vec<&'a Item>
}
impl<'a> App<'a> {
pub fn new() -> App<'a> {
App { items: Vec::new() }
}
pub fn register_item(&mut self, item: &'a Item) {
self.items.push(item);
}
}
pub struct Item;
impl Item {
pub fn new(app: &mut App) -> Item {
let item = Item;
app.register_item(&item);
item
}
}
fn main() {
let mut app = App::new();
let item = Item::new(&mut …Run Code Online (Sandbox Code Playgroud) 我有一个收藏Foo。
struct Foo {
k: String,
v: String,
}
Run Code Online (Sandbox Code Playgroud)
我想要一个HashMap具有键&foo.k和值的键foo。
显然,不Foo通过引入Rc或克隆/复制进行重新设计是不可能的k。
fn t1() {
let foo = Foo { k: "k".to_string(), v: "v".to_string() };
let mut a: HashMap<&str, Foo> = HashMap::new();
a.insert(&foo.k, foo); // Error
}
Run Code Online (Sandbox Code Playgroud)
get()从HashSet(Playground)滥用似乎有一种解决方法:
use std::collections::{HashMap, HashSet};
use std::hash::{Hash, Hasher, BuildHasher};
use std::collections::hash_map::Entry::*;
struct Foo {
k: String,
v: String,
}
impl PartialEq for Foo {
fn eq(&self, …Run Code Online (Sandbox Code Playgroud) 我有一个类型的对象
Arc<RwLock<SessionData>>
Run Code Online (Sandbox Code Playgroud)
我有一种方法应该参考某种形式 SessionData
fn some_method(session: ...)
Run Code Online (Sandbox Code Playgroud)
我正在使用Rocket(Rust的Web框架),我不能直接调用该方法,因为它是由Rocket调用的。但是,我可以为它提供一个实现,该实现创建一个将传递给处理程序的对象。它看起来像这样:
impl<'a, 'r> request::FromRequest<'a, 'r> for SomeType {
type Error = ();
fn from_request(request: &'a request::Request<'r>) -> request::Outcome<Self, Self::Error> {
// return object here
}
}
Run Code Online (Sandbox Code Playgroud)
我想避免RwLock直接返回一个,因为我希望处理程序将一个已经锁定的对象传递给它。但是,我无法返回引用或RwLockReadGuard,因为它们都依赖RwLock,这将超出范围。
相反,我尝试创建某种自给自足的类型,该类型将包含一个Arc<RwLock<SessionData>>,包含此锁的锁保护并取消引用到一个SessionData对象。
到目前为止,我已经尝试了以下几种组合:
Session包含一个对象Arc<RwLock<SessionData>>和一个RwLockReadGuard<SessionData> Arc<RwLock<SessionData>>和一个RwLockReadGuardRef<SessionData>从所属-REF库。OwnedHandle类型的对象。但是,我一直无法做自己想做的事,遇到了各种各样的终身借贷问题。
是否有可能创建一种自成一体的类似“句柄”的对象,同时包含指向它指向的对象的锁和锁保护装置?
这与如何返回对互斥量下的值的子值的引用中所描述的情况类似但略有不同。。在其中,MutexGuardRef内部依赖Mutex,如果Mutex(或MyStruct)超出范围,则内部不存在。为了实现类似的行为,我必须传递一个包含我的结构, …
我正在使用Rocket State,它传递给HTTP请求.此结构包含一个Mutex<DatastoreInstance>访问SQLite数据库的框架,并使用互斥锁锁定以使读写安全.
pub struct DatastoreInstance {
conn: Connection,
}
Run Code Online (Sandbox Code Playgroud)
当DatastoreInstance结构看起来像这样时,只有一个SQLite连接一切正常,但我还想在这个结构中添加一个事务对象:
pub struct DatastoreInstance {
conn: Connection,
events_transaction: Transaction,
}
Run Code Online (Sandbox Code Playgroud)
这没有编译,因为Transaction对象需要引用一个Connection应该具有它所知道的生命周期的对象.我正在使用的rusqlite中的Connection和Transaction对象定义如下:
pub struct Connection {
db: RefCell<InnerConnection>,
cache: StatementCache,
path: Option<PathBuf>,
}
pub struct Transaction<'conn> {
conn: &'conn Connection,
drop_behavior: DropBehavior,
}
Run Code Online (Sandbox Code Playgroud)
要解决生命周期问题,我必须添加这些生命周期参数才能使其正常工作:
pub struct DatastoreInstance<'a> {
conn: Connection,
events_transaction: Transaction<'a>,
}
Run Code Online (Sandbox Code Playgroud)
这是结果,并且应该根据我对生命周期和互斥体的理解而工作,但是我现在得到编译器错误告诉我:
`std::cell::RefCell<lru_cache::LruCache<std::string::String, rusqlite::raw_statement::RawStatement>>` cannot be shared between threads safely
|
= help: within `rusqlite::Connection`, the trait …Run Code Online (Sandbox Code Playgroud) 我有一大堆代码打开文件并逐行搜索内容,然后对每个匹配的行执行某些操作.我想把它考虑到它自己的函数中,它接受一个文件的路径并给你匹配的行,但我无法弄清楚如何正确地考虑这个.
这是我认为很接近的,但是我得到了一个编译器错误:
/// get matching lines from a path
fn matching_lines(p: PathBuf, pattern: &Regex) -> Vec<String> {
let mut buffer = String::new();
// TODO: maybe move this side effect out, hand it a
// stream of lines or otherwise opened file
let mut f = File::open(&p).unwrap();
match f.read_to_string(&mut buffer) {
Ok(yay_read) => yay_read,
Err(_) => 0,
};
let m_lines: Vec<String> = buffer.lines()
.filter(|&x| pattern.is_match(x)).collect();
return m_lines;
}
Run Code Online (Sandbox Code Playgroud)
而编译错误:
src/main.rs:109:43: 109:52 error: the trait `core::iter::FromIterator<&str>` is not implemented for the type …Run Code Online (Sandbox Code Playgroud) 我正在尝试实现一个非常幼稚的线程池模型。目前线程池的职责是:
create一个新线程并返回对其的引用我的主要问题是,上述要求迫使我让线程池保留一些HashMap<Id, Thread>线程,但也在创建线程时提供对线程的引用。
最重要的是,我需要能够从任何线程内部调用线程池的方法,从而有效地最终改变 1 个或多个线程(调用者和目标)。
这是一个非功能性的实现:
use std::collections::HashMap;
use std::cell::RefCell;
type Id = u32;
type ThreadPoolRef = RefCell<ThreadPool>;
#[derive(Debug)]
struct ThreadPool {
pool: HashMap<Id, RefCell<Thread>>,
id_count: Id
}
impl ThreadPool {
fn new() -> ThreadPool {
ThreadPool {
pool: HashMap::new(),
id_count: 1
}
}
fn create(&mut self) -> &RefCell<Thread> {
let thread: RefCell<Thread> =
RefCell::new(
Thread::new(self.id_count, RefCell::new(self))
);
self.id_count = self.id_count + 1;
self.pool.insert(self.id_count, thread);
self.pool.get(&self.id_count).unwrap()
}
}
#[derive(Debug, Clone)]
struct Thread { …Run Code Online (Sandbox Code Playgroud) 我有两个相互依赖的结构。在 C++ 中,我会使用指针来完成此操作,我正在尝试弄清楚如何在 Rust 中执行此操作。到目前为止,我已经尝试使用 Box 和 Rc,我认为由于 Rc 是一个参考计数器,它应该能够处理这个问题,但它给了我一个错误。
这是一个简单的代码示例:
struct A {
b : Rc<B>
}
struct B {
a : Option<Rc<A>>
}
fn main() {
let mut b = B {
a : None
};
let a = A {
b: Rc::new(b)
};
b.a = Some(Rc::new(a));
}
Run Code Online (Sandbox Code Playgroud)
这是我从中得到的错误:
20 | let mut b = B {
| ----- move occurs because `b` has type `B`, which does not implement the `Copy` trait
...
25 | b: Rc::new(b) …Run Code Online (Sandbox Code Playgroud) 以下代码无法编译:
struct Ref<'a> {
nbr: &'a u32,
}
fn func<'a>() {
let nbr: u32 = 42;
let _a_ref: Box<Ref<'a>> = Box::new(Ref { nbr: &nbr });
}
fn main() {
func();
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨说'nbr' does not live long enough,它在仍然借用的末尾被删除func()。我基本上到处都搜索过,但我不明白为什么会出现这个错误。与声明相比,变量应该以相反的顺序删除,因此包含Ref引用的框应该在nbr删除之前删除,对吗?
如果我改成func():
fn func<'a>() {
let nbr: u32 = 42;
let _a_ref = Ref { nbr: &nbr };
}
Run Code Online (Sandbox Code Playgroud)
它构建得很好!因此,盒装参考所需的生命周期/范围存在一些差异 - 但我找不到对这个明显基本问题的任何清晰和简单的解释。
_a_ref为了让它更加混乱,我注意到如果我声明这样的类型:
fn func<'a>() {
let nbr: u32 = 42;
let _a_ref: …Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个由节点组成的单链表,每个节点都有一个对下一个节点的引用,与该节点相关的数据,这是一个有趣的位,即对列表中随机节点的引用.给定节点的随机节点可以出现在节点本身之前,也可以出现在列表中.随机节点是可选的.这是一个图表:
+---------+ +-------------------+
| v v |
+-+--+ ++--++ +----+ +-+--+
+--->+Data+---->+Data+---->+Data+---->+Data|
+-+--+ +----+ +--+-+ +----+
^ |
+----------------------+
Run Code Online (Sandbox Code Playgroud)
该图演示了一个包含四个节点的列表.第一节点的随机引用指向第二节点.缺少第二个节点的随机引用.第三个节点的随机引用是第一个节点.第四个节点的随机引用指向第二个节点.
该列表需要仅支持添加新节点.添加节点后,只要列表存在,就可以通过删除节点使随机引用失效.
我尝试了什么:
我陷入绝对的开端 - 我无法弄清楚如何设计结构以及如何构建列表.这是我在与编译器进行一段时间的摔跤之后得到的代码:
type NodePtr<'a, T> = Option<Box<Node<'a, T>>>;
pub struct Node<'a, T: 'a> {
data: T,
next: NodePtr<'a, T>,
random: Option<&'a Node<'a, T>>,
}
pub struct List<'a, T: 'a> {
root: NodePtr<'a, T>,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn construct() {
let mut list:List<i32> = List {root: Some(Box::new(Node {data: 5, next: None, random: None}))}; …Run Code Online (Sandbox Code Playgroud)