【问题标题】:What's the difference between Hash and NamedTuple in Crystal?Crystal 中的 Hash 和 NamedTuple 有什么区别?
【发布时间】:2018-07-27 15:39:20
【问题描述】:

这两种语法看起来相当相似,它们的用例也很相似。示例:

# Hash
hash = {"name" => "Crystal", "year" => 2011}
hash["name"] # outputs: Crystal

# NamedTuple
tuple = {name: "Crystal", year: 2011}
tuple[:name] # outputs: Crystal

那么这两个原语到底在哪里不同呢?

【问题讨论】:

    标签: syntax crystal-lang


    【解决方案1】:

    API 文档已经很好地解释了这一点。来自NamedTuple(我强调):

    命名元组是固定大小的、不可变的、堆栈分配的一组固定键到值的映射。

    您可以将 NamedTuple 视为一个不可变哈希,其键(属于 Symbol 类型)以及每个键的类型在编译时是已知的

    还有:

    编译器知道每个键中的类型,因此当使用符号文字索引命名元组时,编译器将返回该键的值和预期的类型。使用没有键的符号文字进行索引会产生编译时错误。

    相比之下,Hash

    哈希是键值对的通用集合,将 K 类型的键映射到 V 类型的值。

    简单来说,哈希是一种可以在运行时更改的数据结构,所有键/值都可以具有任何类型,只要它与泛型类型参数 K/V 匹配即可。 另一方面,命名元组是在编译时完全已知的不可变数据结构。如果你访问一个键,编译器就知道它的类型。拥有一个命名元组与将键作为具有公共前缀的变量非常相似:

    foo = {bar: "bar", baz: 1}
    
    foo_bar = "bar"
    foo_baz = 1
    

    NamedTuple 只是添加了一些工具来将这些变量用作一个连贯的集合。

    【讨论】:

    • 那么既然 NameTuple 结构在编译时是完全已知的,这是否意味着它可以被编译器进一步优化,因此比在类似条件下使用 Hash 更快?
    • 没有。请不要在代码中使用 NamedTuple。命名元组只是命名参数的表示。您可能应该始终在代码中使用 Hash 或类。
    • 不过,访问命名元组通常比散列更快。但正如 asterite 所说,您应该对数据结构使用结构/类或哈希,这取决于在编译时是否知道类型和值。
    • @asterite 您的评论在 1.0 中是否仍然正确?我只是偶然发现了一种情况,我有 [] 的方法调用结果并将它们与 + 连接不起作用,因为它试图做 [NamedTuple(x: int32, y: int32)] + [NamedTuple(a: "a")]。 - 语法 {x: 1} 创建 NamedTuple,但 {"x": 1} 创建一个 Hash。- 编辑:刚刚发现你可以将 { :x => 1 } 作为一个 Hash,但 {"x": 1} 创建一个 NamedTuple。所以是一致的。没关系,我只是糊涂了。
    猜你喜欢
    • 2018-11-18
    • 2019-10-18
    • 2010-10-27
    • 2011-12-31
    • 2020-06-15
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多