- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的目标是编译此代码的最后两行并通过最后一个断言:
struct State {
string: String
}
impl State {
fn string<F: FnMut(String) -> String>(mut self, mut f: F) -> Self {
self.string = f(self.string);
self
}
}
fn main() {
let state = State { string: String::from("foo") };
assert_eq!(state.string, "foo");
let state = state.string(|old| old + "bar");
assert_eq!(state.string, "foobar");
// let state = state.string(String::from("baz"));
// assert_eq!(state.string, "baz");
}
我认为这可以通过 traits 和 specialization 来实现,但是下面的代码:
#![feature(specialization)]
trait Get<T> {
fn get(self, old: T) -> T;
}
impl<T> Get<T> for T {
default fn get(self, _: T) -> T {
self
}
}
impl<T, F> Get<T> for F where F: FnMut(T) -> T {
fn get(mut self, old: T) -> T {
self(old)
}
}
struct State {
string: String
}
impl State {
fn string<G: Get<String>>(mut self, g: G) -> Self {
self.string = g.get(self.string);
self
}
}
抛出这个错误(live):
error[E0119]: conflicting implementations of trait `Get<_>`:
--> <anon>:13:1
|
13 | impl<T, F> Get<T> for F where F: FnMut(T) -> T {
| ^
|
note: conflicting implementation is here:
--> <anon>:7:1
|
7 | impl<T> Get<T> for T {
| ^
error: aborting due to previous error
所以我的问题是,为什么 Get 的第二个实现不比第一个实现更“具体”,并且在当前的稳定版或夜间 Rust 中有什么方法可以让我的原始代码工作吗?
编辑:我知道只为一种类型实现特征是可行的,但我想要一个适用于任何类型的通用解决方案,因为我希望能够将其用于结构的任意字段。
最佳答案
对于您的具体问题,您不需要特化:
struct State {
string: String,
}
impl State {
fn string<F>(mut self, mut f: F) -> Self
where F: Thing
{
self.string = f.thing(self.string);
self
}
}
trait Thing {
fn thing(&mut self, s: String) -> String;
}
impl Thing for String {
fn thing(&mut self, _s: String) -> String {
self.clone()
}
}
impl<F> Thing for F
where F: FnMut(String) -> String
{
fn thing(&mut self, s: String) -> String {
(self)(s)
}
}
fn main() {
let state = State { string: String::from("foo") };
assert_eq!(state.string, "foo");
let state = state.string(|old| old + "bar");
assert_eq!(state.string, "foobar");
let state = state.string(String::from("baz"));
assert_eq!(state.string, "baz");
}
您可能想要要求 FnOnce
或为 &str
实现特征。目前,String
的分配未被使用,导致效率低下。
然后您可以为感兴趣的类型多次实现该特征:
struct State {
string: String,
vec: Vec<u8>,
}
impl State {
fn string<F>(mut self, mut f: F) -> Self
where F: Thing<String>
{
self.string = f.thing(self.string);
self
}
fn vec<F>(mut self, mut f: F) -> Self
where F: Thing<Vec<u8>>
{
self.vec = f.thing(self.vec);
self
}
}
trait Thing<T> {
fn thing(&mut self, s: T) -> T;
}
impl Thing<String> for String {
fn thing(&mut self, _s: String) -> String {
self.clone()
}
}
impl<F> Thing<String> for F
where F: FnMut(String) -> String
{
fn thing(&mut self, s: String) -> String {
(self)(s)
}
}
impl Thing<Vec<u8>> for Vec<u8> {
fn thing(&mut self, _s: Vec<u8>) -> Vec<u8> {
self.clone()
}
}
impl<F> Thing<Vec<u8>> for F
where F: FnMut(Vec<u8>) -> Vec<u8>
{
fn thing(&mut self, s: Vec<u8>) -> Vec<u8> {
(self)(s)
}
}
fn main() {
let state = State { string: String::from("foo"), vec: vec![1] };
assert_eq!(state.string, "foo");
let state = state.string(|old| old + "bar");
assert_eq!(state.string, "foobar");
let state = state.string(String::from("baz"));
assert_eq!(state.string, "baz");
assert_eq!(state.vec, [1]);
let state = state.vec(|mut old: Vec<u8>| {
old.push(2);
old
});
assert_eq!(state.vec, [1, 2]);
let state = state.vec(vec![3]);
assert_eq!(state.vec, [3]);
}
我相信重复可以由宏来处理:
macro_rules! thing {
($t: ty) => {
impl Thing<$t> for $t {
default fn thing(&mut self, _val: $t) -> $t {
self.clone()
}
}
impl<F> Thing<$t> for F
where F: FnMut($t) -> $t
{
fn thing(&mut self, val: $t) -> $t {
(self)(val)
}
}
}
}
thing!(String);
thing!(Vec<u8>);
关于rust - 允许函数接受 `T` 或任何 `FnMut(T) -> T`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38811099/
给定一个 Rc ,在迭代器上映射时如何使用它?例如: use std::rc::Rc; fn main() { let f = Rc::new(|x| x); let v = vec!
use std::cell::RefCell; use std::rc::Rc; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; fn
我有第三方库,代码如下: pub struct Foo { t: T } impl Foo where T: 'a + FnMut() -> &'a [u8] { pub fn from_ca
我正在尝试拥有一组可以采用 CharPredicate 的函数这是我自己的特征,通过 FnMut(char) -> bool 实现, Range , char等 目标是能够像这样调用助手: scan_
我有以下代码: struct Callable { callable: Box, } struct Parameters { text: &'a str, } struct Conte
这是一个可以组合Fn 闭包的compose 函数: fn compose(f: F1, g: F2) -> Box T3 + 'a> where F1: Fn(T1) -> T2 + 'a,
我正在为 Rust 编写一个 Phoenix 客户端库,利用来自 rust-websockets 的异步 websocket 客户端.现在我无法弄清楚如何将回调函数传递到处理 websocket 流量
pub fn create_future( notificator: mpsc::Sender, proxy: Proxy, ) -> impl Future { proxy.
背景:我试图避免使用 Mutex/RefCell/Option在嵌入式系统的中断处理程序中跳舞。我不想使用堆(而且我不认为它应该是必要的——但随时告诉我错误)。我不能使用 std .我看过 corte
如何在需要 FnMut 类型的上下文中使用盒装闭包,例如 pub fn main() { for n in (0..10).map(Box::new(|i| i * 2)) { print
我有一个类似这样的struct: struct Foo { callbacks: Vec, } 我想调用每个回调,但我的尝试不起作用: fn foo(&mut self) { for
这是来自 Rust by Example 的示例: pub trait Iterator { // The type being iterated over. type Item;
我正在尝试返回一个以 &Any 作为参数的闭包。以下代码返回编译器错误。 trait Selector { fn id(&self) -> i64; fn selector(&self
我想使用 FnMut(&[f32]) -> f32,为了不复制/粘贴完整签名,我想引入某种别名,但是 type Boo = FnMut(&[f32]) -> f32; fn f(mut f: F) {
自从 Iter's "all" fn takes type FnMut是否可以在检查条件和短路时更新元素?虽然我知道它不应该这样做,但是是什么阻止它更新值? fn main() { let a
我有以下代码片段,它实现了某种发射器结构: type Callback = Option; struct Emitter { cb: Callback } impl Emitter { fn
我已经通用实现了callback_list_stream,但是我似乎无法以专门的方式使用它。如果我按照T复制/粘贴代码,则该代码有效。 use futures::channel::mpsc::Rece
我有一个函数,collect_n ,返回 Future反复polls一个 futures::sync::mpsc::Receiver并将结果收集到一个向量中,并使用该向量进行解析。问题是它消耗了 Re
我正在尝试创建一个简单的程序,其中包含一个包含逐渐清空自身的集合的闭包: fn main() { let vector = vec![1, 2, 3]; let mut allow_o
基本上,我想编写一个返回闭包的函数。我怎样才能做到这一点而不必返回 Box ? 来自closures chapter of the rust book ,我读到闭包只是结构的语法糖和 FnOnce 的
我是一名优秀的程序员,十分优秀!