Rust 什么是TypeScript hashmap的等价物,该hashmap具有特定键的可选类型化值?
我希望能够有一个数据结构,它可以有具有特定类型的键,比如Rust结构,但是可以有可选值,这些值不需要像HashMap那样存在。是否存在介于两者之间的数据类型?最好的方法是什么 我正在学习Rust,但每天都要使用TypeScript。我知道这两种类型的系统是不同的,我只是想实现一些相似的东西。在TypeScript中,我可以执行以下操作: 接口示例{ value1:字符串; 可选?:编号; 价值3?:你好|再见; } 创建与之匹配的对象时: 常量对象:示例={ 价值1:这很有效 } 我正在探索如何做出贡献,我想尝试的第一件事是以惯用的方式实现。能够在具有特定枚举类型flex、block等的结构中声明样式,但不需要每个可能的样式/CSS选择器,这是此类库的关键Rust 什么是TypeScript hashmap的等价物,该hashmap具有特定键的可选类型化值?,rust,Rust,我希望能够有一个数据结构,它可以有具有特定类型的键,比如Rust结构,但是可以有可选值,这些值不需要像HashMap那样存在。是否存在介于两者之间的数据类型?最好的方法是什么 我正在学习Rust,但每天都要使用TypeScript。我知道这两种类型的系统是不同的,我只是想实现一些相似的东西。在TypeScript中,我可以执行以下操作: 接口示例{ value1:字符串; 可选?:编号; 价值3?:你好|再见; } 创建与之匹配的对象时: 常量对象:示例={ 价值1:这很有效 } 我正在探索如何
欢迎使用任何示例。TypeScript和JavaScript有两种:null和undefined 大多数其他语言最初没有,因为拥有两种选项类型cf.from;并不是一个明确的胜利 在Rust中,您将使用,而大多数情况下,它都对应于JavaScript和TypeScript的null和未定义
struct Example {
value1: String,
optional: Option<i64>,
value3: Option<String>
}
TypeScript和JavaScript有两种:null和undefined 大多数其他语言最初没有,因为拥有两种选项类型cf.from;并不是一个明确的胜利 在Rust中,您将使用,而大多数情况下,它都对应于JavaScript和TypeScript的null和未定义
struct Example {
value1: String,
optional: Option<i64>,
value3: Option<String>
}
这不是Rust中HashMaps的用例。HashMap的键在编译时是未知的,这不是您想要的。结构有一组固定的已知键,而枚举有一组固定的可能性 代码的直接转换将创建一个结构和一个枚举,使用选项表示可选字段:
#[derive(Debug)]
struct Example {
value1: String,
optional: Option<i32>,
value3: Option<Value3Values>,
}
#[derive(Debug)]
enum Value3Values {
Hello,
Goodbye,
}
我们可以应用一些步骤来改进它。使用Default加上struct literal update语法可以简化所有默认值:
#[derive(Debug, Default)]
struct Example { /* ... */ }
然后,您还可以应用Into/From特征来删除一些转换:
Example {
value1: "hello".into(),
value3: Value3Values::Goodbye.into(),
..Example::default()
}
您可以将其包装在宏中以避免重复:
macro_rules! thing {
($t:ident, { $( $name:ident : $val:expr ),*, }) => (
$t {
$( $name: Into::into($val) ),*,
.. $t::default()
}
);
}
fn main() {
thing!(Example, {
value1: "hello",
});
thing!(Example, {
value1: "hello",
optional: 32,
});
thing!(Example, {
value1: "hello",
value3: Value3Values::Hello,
});
thing!(Example, {
value1: "hello",
optional: 32,
value3: Value3Values::Hello,
});
}
对于value3,甚至有使用字符串文字的方法,但我会避免使用它。严格类型的API令人讨厌
macro_rules! value3 {
("hello") => (Value3Values::Hello);
("goodbye") => (Value3Values::Goodbye);
}
fn main() {
thing!(Example, {
value1: "hello",
value3: value3!("hello"),
});
thing!(Example, {
value1: "hello",
optional: 32,
value3: value3!("goodbye"),
});
}
甚至可能有更聪明的宏技巧来避免调用宏值3!里面的东西
一种非常先进的技术是使用为每一组CSS属性生成自定义宏,可能使用。你会得到这样的结果:
macro_rules! example {
( $( $name:ident : $val:tt ),*, ) => (
Example {
$( $name: example!(field @ $name : $val) ),*,
.. Example::default()
}
);
// Internal details
( field @ value1 : $val:expr ) => (Into::into($val));
( field @ optional : $val:expr ) => (Into::into($val));
( field @ value3 : hello ) => (Some(Value3Values::Hello));
( field @ value3 : goodbye ) => (Some(Value3Values::Goodbye));
( field @ value3 : $val:expr ) => (
compile_error!(r#"value3 can only be "hello" or "goodbye""#)
);
}
fn main() {
example! {
value1: "name",
};
example! {
optional: 42,
};
example! {
value1: "name",
value3: hello,
};
example! {
value1: "name",
optional: 42,
value3: goodbye,
};
}
这不是Rust中HashMaps的用例。HashMap的键在编译时是未知的,这不是您想要的。结构有一组固定的已知键,而枚举有一组固定的可能性 代码的直接转换将创建一个结构和一个枚举,使用选项表示可选字段:
#[derive(Debug)]
struct Example {
value1: String,
optional: Option<i32>,
value3: Option<Value3Values>,
}
#[derive(Debug)]
enum Value3Values {
Hello,
Goodbye,
}
我们可以应用一些步骤来改进它。使用Default加上struct literal update语法可以简化所有默认值:
#[derive(Debug, Default)]
struct Example { /* ... */ }
然后,您还可以应用Into/From特征来删除一些转换:
Example {
value1: "hello".into(),
value3: Value3Values::Goodbye.into(),
..Example::default()
}
您可以将其包装在宏中以避免重复:
macro_rules! thing {
($t:ident, { $( $name:ident : $val:expr ),*, }) => (
$t {
$( $name: Into::into($val) ),*,
.. $t::default()
}
);
}
fn main() {
thing!(Example, {
value1: "hello",
});
thing!(Example, {
value1: "hello",
optional: 32,
});
thing!(Example, {
value1: "hello",
value3: Value3Values::Hello,
});
thing!(Example, {
value1: "hello",
optional: 32,
value3: Value3Values::Hello,
});
}
对于value3,甚至有使用字符串文字的方法,但我会避免使用它。严格类型的API令人讨厌
macro_rules! value3 {
("hello") => (Value3Values::Hello);
("goodbye") => (Value3Values::Goodbye);
}
fn main() {
thing!(Example, {
value1: "hello",
value3: value3!("hello"),
});
thing!(Example, {
value1: "hello",
optional: 32,
value3: value3!("goodbye"),
});
}
甚至可能有更聪明的宏技巧来避免调用宏值3!里面的东西
一种非常先进的技术是使用为每一组CSS属性生成自定义宏,可能使用。你会得到这样的结果:
macro_rules! example {
( $( $name:ident : $val:tt ),*, ) => (
Example {
$( $name: example!(field @ $name : $val) ),*,
.. Example::default()
}
);
// Internal details
( field @ value1 : $val:expr ) => (Into::into($val));
( field @ optional : $val:expr ) => (Into::into($val));
( field @ value3 : hello ) => (Some(Value3Values::Hello));
( field @ value3 : goodbye ) => (Some(Value3Values::Goodbye));
( field @ value3 : $val:expr ) => (
compile_error!(r#"value3 can only be "hello" or "goodbye""#)
);
}
fn main() {
example! {
value1: "name",
};
example! {
optional: 42,
};
example! {
value1: "name",
value3: hello,
};
example! {
value1: "name",
optional: 42,
value3: goodbye,
};
}
这是有道理的,但是当创建具有这些选项参数的结构时,如果您忽略了这些可选字段,则在启动结构时会发出抱怨。如果我要创建一个类型来描述所有可能的CSS样式,比如背景色,那么就不可能使用它,因为你需要列出每个不使用的字段,在这种情况下可能会有数百个。@AlexanderMattoni Default可能会有所帮助,我在答案中添加了一个例子。我不是JS人,但我认为你没有正确使用底部这个词。null是一个值,不是一个类型,对吧?这很有意义,但当创建一个包含这些选项参数的结构时,如果您忽略了这些可选字段,它会在启动结构时发出抱怨。如果我要创建一个类型来描述所有可能的CSS样式,比如背景色,那么就不可能使用它,因为你需要列出每个不使用的字段,在这种情况下可能会有数百个。@AlexanderMattoni Default可能会有所帮助,我在答案中添加了一个例子。我不是JS人,但我认为你没有正确使用底部这个词。null是一个值,不是一个类型,对吗?哇,谢谢你的深入回答。宏语法对我来说非常陌生,但我会看一看。这离我想做的事情更近了。我会
我沿着这条路走,看看路怎么走。这非常令人兴奋,而且不必再触碰javascript的想法非常吸引人:。顺便说一句,自由风格允许使用任意CSS选择器键,i.e.&>div::hover等。你认为在像这样的库中处理锈菌的最好方法是什么?@AlexanderMattoni我不能回答这个问题,因为在这个问题中没有任何选择器被引用,所以我没有必要提供任何有用的上下文。哇,谢谢你的深入回答。宏语法对我来说非常陌生,但我会看一看。这离我想做的事情更近了。我会沿着这条路走下去,看看路是怎么走的。这非常令人兴奋,而且不必再触碰javascript的想法非常吸引人:。顺便说一句,自由风格允许使用任意CSS选择器键,i.e.&>div::hover等。你认为在像这样的库中,什么是解决锈病的最佳方法?@AlexanderMattoni我不能回答这个问题,因为在这个问题中没有任何选择器被引用,所以我没有必要提供任何有用的上下文。