Rust 什么是TypeScript hashmap的等价物,该hashmap具有特定键的可选类型化值?

Rust 什么是TypeScript hashmap的等价物,该hashmap具有特定键的可选类型化值?,rust,Rust,我希望能够有一个数据结构,它可以有具有特定类型的键,比如Rust结构,但是可以有可选值,这些值不需要像HashMap那样存在。是否存在介于两者之间的数据类型?最好的方法是什么 我正在学习Rust,但每天都要使用TypeScript。我知道这两种类型的系统是不同的,我只是想实现一些相似的东西。在TypeScript中,我可以执行以下操作: 接口示例{ value1:字符串; 可选?:编号; 价值3?:你好|再见; } 创建与之匹配的对象时: 常量对象:示例={ 价值1:这很有效 } 我正在探索如何

我希望能够有一个数据结构,它可以有具有特定类型的键,比如Rust结构,但是可以有可选值,这些值不需要像HashMap那样存在。是否存在介于两者之间的数据类型?最好的方法是什么

我正在学习Rust,但每天都要使用TypeScript。我知道这两种类型的系统是不同的,我只是想实现一些相似的东西。在TypeScript中,我可以执行以下操作:

接口示例{ value1:字符串; 可选?:编号; 价值3?:你好|再见; } 创建与之匹配的对象时:

常量对象:示例={ 价值1:这很有效 } 我正在探索如何做出贡献,我想尝试的第一件事是以惯用的方式实现。能够在具有特定枚举类型flex、block等的结构中声明样式,但不需要每个可能的样式/CSS选择器,这是此类库的关键


欢迎使用任何示例。

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我不能回答这个问题,因为在这个问题中没有任何选择器被引用,所以我没有必要提供任何有用的上下文。