我想创建一个Rc<str>
因为我想减少间接跟随访问Rc<String>
需求的2个指针.我需要使用一个,Rc
因为我真的拥有共享权.我详细介绍了我在字符串类型中遇到的更具体问题.
Rc 有一个?Sized
约束:
pub struct Rc<T: ?Sized> { /* fields omitted */ }
Run Code Online (Sandbox Code Playgroud)
我还听说Rust 1.2将提供适当的支持来存储未经过类型化的类型Rc
,但我不确定它与1.1的区别.
以str
案例为例,我的天真尝试(也就是从a构建String
)也失败了:
use std::rc::Rc;
fn main() {
let a: &str = "test";
let b: Rc<str> = Rc::new(*a);
println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> src/main.rs:5:22
|
5 | let b: Rc<str> = Rc::new(*a);
| ^^^^^^^ `str` does not have …
Run Code Online (Sandbox Code Playgroud) 我的这个片段没有通过借阅检查器:
use std::collections::HashMap;
enum Error {
FunctionNotFound,
}
#[derive(Copy, Clone)]
struct Function<'a> {
name: &'a str,
code: &'a [u32],
}
struct Context<'a> {
program: HashMap<&'a str, Function<'a>>,
call_stack: Vec<Function<'a>>,
}
impl<'a> Context<'a> {
fn get_function(&'a mut self, fun_name: &'a str) -> Result<Function<'a>, Error> {
self.program
.get(fun_name)
.map(|f| *f)
.ok_or(Error::FunctionNotFound)
}
fn call(&'a mut self, fun_name: &'a str) -> Result<(), Error> {
let fun = try!(self.get_function(fun_name));
self.call_stack.push(fun);
Ok(())
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
error[E0499]: cannot borrow `self.call_stack` as mutable more than …
Run Code Online (Sandbox Code Playgroud) 对于大多数程序,最好在内部使用UTF-8,并在必要时转换为其他编码.但在我的情况下,我想编写一个Javascript解释器,并且只存储UTF-16字符串(或数组u16
)更简单,因为
我需要单独处理16位代码单元(这通常是一个坏主意,但Javascript需要这个).这意味着我需要它来实现Index<usize>
.
我需要存储不成对代理人,即,畸形UTF-16的字符串(正因为如此,ECMAScript的字符串在技术上定义为阵列u16
,其通常代表UTF-16的字符串).有一个名为WTF-8的编码用于存储UTF-8中不成对的代理,但我不想使用这样的东西.
我希望拥有通常拥有/借用的类型(如String
/ str
和CString
/ CStr
)以及所有或最常用的方法.我不想滚动自己的字符串类型(如果我可以避免).
此外,我的字符串将始终是不可变的,位于Rc
包含指向所有字符串的弱指针的数据结构后面(并实现字符串实习).这可能是相关的:也许最好是Rc<Utf16Str>
作为字符串类型,其中Utf16Str
是未定义的字符串类型(可以定义为just struct Utf16Str([u16])
).这样可以避免在访问字符串时遵循两个指针,但我不知道如何Rc
使用unsized类型实例化.
鉴于上述要求,仅使用防锈编码非常不方便,因为它将所有非UTF-8编码视为矢量u8
.
另外,我不确定使用std库是否可以帮助我.我调查了Utf16Units
它,它只是一个迭代器,而不是一个正确的字符串类型.(另外,我知道OsString
没有帮助 - 我不在Windows上,甚至没有实现Index<usize>
)
我想创建一个应用程序,我在窗口上绘制,无论是窗口还是全屏,我抓住鼠标但没有拦截任何 WM键盘快捷键,如Alt + Tab,我还需要在用户进入/离开时收到通知焦点.
谷歌Chrome,Firefox或gnome-terminal等常见应用程序可以很好地处理这个问题(使用F11全屏,但仍然使用Alt + Tab),但他们不会抓住鼠标.
SDL对此用例的处理方式臭名昭着:SDL_WM_GrabInput抓取鼠标但也拦截WM快捷方式; 和SDL_FULLSCREEN似乎有一些自动抓取(不要问我为什么).
一个解决方案可能是自己为Alt + Tab编写代码,但这很糟糕(并且对其他WM快捷方式没有帮助,比如更改到另一个工作区).
另一个解决方案是不调用SDL_WM_GrabInput,而是伪造一个抓取:只需隐藏鼠标指针(使用SDL_ShowCursor)并在用户移动时将其移回中心.这是丑陋的,但在实践中工作 - 当然除了SDL_FULLSCREEN,因为它自动抓取(不同于理智的实现).这是一个全屏功能的SDL解决方案,但这仍然不是我想要的.我不想有黑客来启用和禁用抓取,我想抓住鼠标而不是抓住键盘.
所以我对SDL很生气,并希望看到其他选择.我想使用SDL,但这不是必需的.
这个问题似乎指出SDL实际上做的是使用XGrabKeyboard.通过阅读手册页,我不清楚你是否可以在不抓取键盘的情况下抓住鼠标(我自己从未使用过Xlib).
我知道如何使用GTK制作"假全屏"(即Alt + Tab友好,gnome-terminal类型).我想这样做,加上鼠标隐藏并将其移回中心("假抓取")可以做到这一点,但这感觉就像是过多的胶带.必须有一个更简单的方法.(另外我不想将GTK添加为依赖项;但我也不确定是否进行原始Xlib调用是一个好主意).
对此有什么好的解决方案?
我需要一个Linux/X11解决方案但是跨平台它会很好 - 我知道这可以在Windows上顺利解决,所以也许有一个库正是这样做的.(另外,我用OpenGL渲染,但这是无关紧要的)
PS:也许我对这个问题了解不多,而且我没有问正确的问题,所以请随意指出我没有考虑过的方法.
如果我有类型的类型MyEnum<T>
,如果不是每个变量都参数化,我怎么能映射它?
例如,我想转换MyEnum<u32>
为MyEnum<String>
:
enum MyEnum<T> {
B,
C,
D(T),
}
fn trans(a: MyEnum<u32>) -> MyEnum<String> {
match a {
MyEnum::D(i) => MyEnum::D(i.to_string()),
other_cases => other_cases,
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
这失败了:
error[E0308]: match arms have incompatible types
--> src/main.rs:8:9
|
8 | match a {
| ^ expected struct `std::string::String`, found u32
|
= note: expected type `MyEnum<std::string::String>`
= note: found type `MyEnum<u32>`
note: match arm with an incompatible type
--> src/main.rs:10:28
|
10 | …
Run Code Online (Sandbox Code Playgroud) 我有以下代码,其中fac
return (MyType, OtherType)
:
let l = (-1..13).map(|x| {
fac(x).0
}).collect::<Vec<MyType>>();
Run Code Online (Sandbox Code Playgroud)
它有效,但我正在丢弃这些OtherType
值。所以我决定使用.unzip
,像这样:
let (v, r) = (-1..13).map(|x| {
fac(x)
}).unzip();
let l = v.collect::<Vec<MyType>>();
let q = r.collect::<Vec<OtherType>>();
Run Code Online (Sandbox Code Playgroud)
但是类型推断失败了:
error: the type of this value must be known in this context
let l = v.collect::<Vec<Literal>>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~
let q = r.collect::<Vec<OtherType>>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
问题是:我不知道也不关心迭代器的具体类型是什么(我认为编译器可以推断它们,如第一个片段所示)。在这种情况下如何满足编译器?
另外,我宁愿重组的代码-我不喜欢单独通话.collect()
双方v
和r
。理想情况下,我会在 之后继续方法链.unzip()
,Vec
在该表达式中返回两个s。