Last active
July 19, 2024 06:19
-
-
Save towry/ad7280a6b16e63530d91ac2c1397a944 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug)] | |
enum AnyValue { | |
String(String), | |
Number(i64), | |
} | |
// let a: &'str = convert(&value) | |
// let b: i64 = convert(&value) | |
fn convert<'a, T: ConvertFromValue<'a> + 'static>(value: &AnyValue) -> Option<T> { | |
T::convert_from_value(value) | |
} | |
trait ConvertFromValue<'a>: Sized { | |
fn convert_from_value(value: &AnyValue) -> Option<Self>; | |
} | |
impl ConvertFromValue<'_> for String { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v.clone()), | |
_ => None, | |
} | |
} | |
} | |
struct ArgCallback { | |
f: Box<dyn Fn(&AnyValue)->AnyValue> | |
} | |
impl ArgCallback { | |
fn new<'a, F, Arg>(cb: F) -> Self where F: CallbackTrait<'a, Arg> + 'static, Arg: ConvertFromValue<'a> { | |
ArgCallback { | |
f: Box::new(move |value: &AnyValue| -> AnyValue { | |
cb.invoke(Arg::convert_from_value(&value).unwrap()) | |
}) | |
} | |
} | |
fn invoke(self, value: &AnyValue) -> AnyValue { | |
(self.f)(value) | |
} | |
} | |
trait CallbackTrait<'a, Arg> where Arg: ConvertFromValue<'a> { | |
fn invoke(&self, arg: Arg) -> AnyValue; | |
} | |
// let sqaure = ArgCallback::new(|v| AnyValue::Number(v * 2)) | |
// sqaure.invoke(23) | |
fn main() { | |
let value = AnyValue::String("23".to_owned()); | |
let strvalue = convert::<String>(&value); | |
println!("{:?}", strvalue); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug)] | |
enum AnyValue { | |
String(String), | |
Number(i64), | |
} | |
// let a: &'str = convert(&value) | |
// let b: i64 = convert(&value) | |
fn convert<'a, T: ConvertFromValue<'a> + 'static>(value: &AnyValue) -> Option<T> { | |
T::convert_from_value(value) | |
} | |
trait ConvertFromValue<'a>: Sized { | |
fn convert_from_value(value: &AnyValue) -> Option<Self>; | |
} | |
impl ConvertFromValue<'_> for String { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v.clone()), | |
_ => None, | |
} | |
} | |
} | |
struct ArgCallback<'l> { | |
f: Box<dyn Fn(&AnyValue)->AnyValue + 'l> | |
} | |
impl<'l> ArgCallback<'l> { | |
fn new<'a, F, Arg>(cb: F) -> Self where F: CallbackTrait<'a, Arg> + 'l, Arg: ConvertFromValue<'a> { | |
ArgCallback { | |
f: Box::new(move |value: &AnyValue| -> AnyValue { | |
cb.invoke(Arg::convert_from_value(&value).unwrap()) | |
}) | |
} | |
} | |
fn invoke(self, value: &AnyValue) -> AnyValue { | |
(self.f)(value) | |
} | |
} | |
trait CallbackTrait<'a, Arg> where Arg: ConvertFromValue<'a> { | |
fn invoke(&self, arg: Arg) -> AnyValue; | |
} | |
// let sqaure = ArgCallback::new(|v| AnyValue::Number(v * 2)) | |
// sqaure.invoke(23) | |
fn main() { | |
let value = AnyValue::String("23".to_owned()); | |
let strvalue = convert::<String>(&value); | |
println!("{:?}", strvalue); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug)] | |
enum AnyValue { | |
String(String), | |
Number(i64), | |
} | |
// let a: &'str = convert(&value) | |
// let b: i64 = convert(&value) | |
fn convert<'a, T: ConvertFromValue<'a> + 'static>(value: &AnyValue) -> Option<T> { | |
T::convert_from_value(value) | |
} | |
trait ConvertFromValue<'a>: Sized { | |
fn convert_from_value(value: &AnyValue) -> Option<Self>; | |
} | |
impl ConvertFromValue<'_> for String { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v.clone()), | |
_ => None, | |
} | |
} | |
} | |
impl ConvertFromValue<'_> for i64 { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::Number(x) => Some(x.clone()), | |
_ => None, | |
} | |
} | |
} | |
struct ArgCallback<'l> { | |
f: Box<dyn Fn(&AnyValue) -> AnyValue + 'l>, | |
} | |
impl<'l> ArgCallback<'l> { | |
fn new<'a, F, Arg>(cb: F) -> Self | |
where | |
F: CallbackTrait<'a, Arg> + 'l, | |
Arg: ConvertFromValue<'a>, | |
{ | |
ArgCallback { | |
f: Box::new(move |value: &AnyValue| -> AnyValue { | |
cb.invoke(Arg::convert_from_value(&value).unwrap()) | |
}), | |
} | |
} | |
fn invoke(self, value: &AnyValue) -> AnyValue { | |
(self.f)(value) | |
} | |
} | |
trait CallbackTrait<'a, Arg> | |
where | |
Arg: ConvertFromValue<'a>, | |
{ | |
fn invoke(&self, arg: Arg) -> AnyValue; | |
} | |
impl<'a, Arg, F> CallbackTrait<'a, Arg> for F | |
where | |
F: Fn(Arg) -> AnyValue, | |
Arg: ConvertFromValue<'a>, | |
{ | |
fn invoke(&self, arg: Arg) -> AnyValue { | |
(self)(arg) | |
} | |
} | |
// let sqaure = ArgCallback::new(|v| AnyValue::Number(v * 2)) | |
// sqaure.invoke(23) | |
fn main() { | |
// let value = AnyValue::String("23".to_owned()); | |
let sqaure = ArgCallback::new(|x: i64| AnyValue::Number(x * 2)); | |
println!("{:?}", sqaure.invoke(&AnyValue::Number(2))); | |
let join_string = ArgCallback::new(|x: String| AnyValue::String(x + " World!")); | |
println!( | |
"{:?}", | |
join_string.invoke(&AnyValue::String("Hello".to_owned())) | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug)] | |
enum AnyValue { | |
String(String), | |
Number(i64), | |
} | |
// let a: &'str = convert(&value) | |
// let b: i64 = convert(&value) | |
fn convert<'a, T: ConvertFromValue<'a> + 'static>(value: &'a AnyValue) -> Option<T> { | |
T::convert_from_value(value) | |
} | |
trait ConvertFromValue<'a>: Sized { | |
fn convert_from_value(value: &'a AnyValue) -> Option<Self>; | |
} | |
impl ConvertFromValue<'_> for String { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v.clone()), | |
_ => None, | |
} | |
} | |
} | |
impl ConvertFromValue<'_> for i64 { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::Number(x) => Some(x.clone()), | |
_ => None, | |
} | |
} | |
} | |
impl<'a> ConvertFromValue<'a> for &'a str { | |
fn convert_from_value(value: &'a AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v), | |
_ => None, | |
} | |
} | |
} | |
struct ArgCallback<'l> { | |
f: Box<dyn Fn(&'l AnyValue) -> AnyValue + 'l>, | |
} | |
impl<'l> ArgCallback<'l> { | |
fn new<'a, F, Arg>(cb: F) -> Self | |
where | |
'l: 'a, | |
F: CallbackTrait<'a, Arg> + 'l, | |
Arg: ConvertFromValue<'a>, | |
{ | |
// 这里,我们需要将这个闭包 连同 闭包需要的变量一起捕获,然后被 | |
// ArgCallback 所拥有,所以,捕获的数据的生命周期需要比 ArgCallback 的数据长久。 | |
// 即比 `'l` 长久。 | |
// 所以,cb 要比 l 长久,cb所持有或者引用的数据需要比 l 长久,其中包括 cb 的生命周期 a。 | |
ArgCallback { | |
f: Box::new(move |value: &AnyValue| -> AnyValue { | |
cb.invoke(Arg::convert_from_value(&value).unwrap()) | |
}), | |
} | |
} | |
// 因为 ArgCallback 需要生存至少 l 的生命周期,那么它引用的数据或者拥有的数据 | |
// 必须要至少生存这么长时间。那么传递给它的方法的引用也要和它self的生命周期的关系 | |
// 有正确的语义(方法invoke是ArgCallback上的一个属性,属于ArgCallback)。 | |
// 如果 | |
// ArgCallback有多个生命周期的话,那么最短的那个生命周期明显是ArgCallback至少要生存的周期。 | |
fn invoke<'c: 'l>(self, value: &'c AnyValue) -> AnyValue { | |
(self.f)(value) | |
} | |
} | |
trait CallbackTrait<'a, Arg> | |
where | |
Arg: ConvertFromValue<'a>, | |
{ | |
fn invoke(&self, arg: Arg) -> AnyValue; | |
} | |
impl<'a, Arg, F> CallbackTrait<'a, Arg> for F | |
where | |
F: Fn(Arg) -> AnyValue, | |
Arg: ConvertFromValue<'a>, | |
{ | |
fn invoke(&self, arg: Arg) -> AnyValue { | |
(self)(arg) | |
} | |
} | |
// let sqaure = ArgCallback::new(|v| AnyValue::Number(v * 2)) | |
// sqaure.invoke(23) | |
fn main() { | |
// let value = AnyValue::String("23".to_owned()); | |
let sqaure = ArgCallback::new(|x: i64| AnyValue::Number(x * 2)); | |
println!("{:?}", sqaure.invoke(&AnyValue::Number(2))); | |
let join_string = ArgCallback::new(|x: String| AnyValue::String(x + " World!")); | |
println!( | |
"{:?}", | |
join_string.invoke(&AnyValue::String("Hello".to_owned())) | |
); | |
} | |
#[test] | |
fn test_me() { | |
assert_eq!(2, 2); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug)] | |
enum AnyValue { | |
String(String), | |
Number(i64), | |
} | |
// let a: &'str = convert(&value) | |
// let b: i64 = convert(&value) | |
#[allow(dead_code)] | |
fn convert<'a, T: ConvertFromValue<'a> + 'static>(value: &'a AnyValue) -> Option<T> { | |
T::convert_from_value(value) | |
} | |
trait ConvertFromValue<'a>: Sized { | |
fn convert_from_value(value: &'a AnyValue) -> Option<Self>; | |
} | |
impl ConvertFromValue<'_> for String { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v.clone()), | |
_ => None, | |
} | |
} | |
} | |
impl ConvertFromValue<'_> for i64 { | |
fn convert_from_value(value: &AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::Number(x) => Some(*x), | |
_ => None, | |
} | |
} | |
} | |
impl<'a> ConvertFromValue<'a> for &'a str { | |
fn convert_from_value(value: &'a AnyValue) -> Option<Self> { | |
match value { | |
AnyValue::String(v) => Some(v), | |
_ => None, | |
} | |
} | |
} | |
struct ArgCallback<'l> { | |
f: Box<dyn Fn(&'l AnyValue) -> Option<AnyValue> + 'l>, | |
} | |
impl<'l> ArgCallback<'l> { | |
fn new<'a, F, Arg>(cb: F) -> Self | |
where | |
'l: 'a, | |
F: CallbackTrait<'a, Arg> + 'l, | |
Arg: ConvertFromValue<'a>, | |
{ | |
// 这里,我们需要将这个闭包 连同 闭包需要的变量一起捕获,然后被 | |
// ArgCallback 所拥有,所以,捕获的数据的生命周期需要比 ArgCallback 的数据长久。 | |
// 即比 `'l` 长久。 | |
// 所以,cb 要比 l 长久,cb所持有或者引用的数据需要比 l 长久,其中包括 cb 的生命周期 a。 | |
ArgCallback { | |
f: Box::new(move |value: &AnyValue| -> Option<AnyValue> { | |
let arg = Arg::convert_from_value(value)?; | |
cb.invoke(arg) | |
}), | |
} | |
} | |
// 因为 ArgCallback 需要生存至少 l 的生命周期,那么它引用的数据或者拥有的数据 | |
// 必须要至少生存这么长时间。那么传递给它的方法的引用也要和它self的生命周期的关系 | |
// 有正确的语义(方法invoke是ArgCallback上的一个属性,属于ArgCallback)。 | |
// 如果 | |
// ArgCallback有多个生命周期的话,那么最短的那个生命周期明显是ArgCallback至少要生存的周期。 | |
fn invoke<'c: 'l>(self, value: &'c AnyValue) -> Option<AnyValue> { | |
(self.f)(value) | |
} | |
} | |
trait CallbackTrait<'a, Arg> | |
where | |
Arg: ConvertFromValue<'a>, | |
{ | |
fn invoke(&self, arg: Arg) -> Option<AnyValue>; | |
} | |
impl<'a, Arg, F> CallbackTrait<'a, Arg> for F | |
where | |
F: Fn(Arg) -> Option<AnyValue>, | |
Arg: ConvertFromValue<'a>, | |
{ | |
fn invoke(&self, arg: Arg) -> Option<AnyValue> { | |
(self)(arg) | |
} | |
} | |
// let sqaure = ArgCallback::new(|v| AnyValue::Number(v * 2)) | |
// sqaure.invoke(23) | |
fn main() { | |
// let value = AnyValue::String("23".to_owned()); | |
let sqaure = ArgCallback::new(|x: i64| Some(AnyValue::Number(x * 2))); | |
println!("{:?}", sqaure.invoke(&AnyValue::Number(2))); | |
let join_string = ArgCallback::new(|x: String| Some(AnyValue::String(x + " World!"))); | |
println!( | |
"{:?}", | |
join_string.invoke(&AnyValue::String("Hello".to_owned())) | |
); | |
let join_strs = ArgCallback::new(|x: &str| Some(AnyValue::String(x.to_string() + " ok"))); | |
println!("{:?}", join_strs.invoke(&AnyValue::String("Hi".to_owned()))); | |
let test_none = ArgCallback::new(|x: &str| Some(AnyValue::String(x.to_string() + " ok"))); | |
println!("{:?}", test_none.invoke(&AnyValue::Number(33))); | |
} | |
#[test] | |
fn test_me() { | |
assert_eq!(2, 2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment