【问题标题】:Is there a way to use non Tuple objects with splat operator in Crystal?有没有办法在 Crystal 中使用带有 splat 运算符的非 Tuple 对象?
【发布时间】:2018-08-16 04:21:15
【问题描述】:

是否有一些函数或语法结构可以使下一个示例工作?

使用Array 参数调用Hash#values_at 函数:

h = {"a" => 1, "b" => 2, "c" => 3}
ary = ["a", "b"]
h.values_at(*ary) # Error: argument to splat must be a tuple, not Array(String)

传递Hash 来初始化类或结构:

struct Point                                                                                                 
    def initialize(@x : Int32, @y : Int32)                                                                     
    end                                                                                                        
end
h = {"x" => 1, "y" => 2}
Point.new(**h) # Error: argument to double splat must be a named tuple, not Hash(String, Int32)

【问题讨论】:

  • 我相信简短的回答是否定的。但我发现,根据您要完成的工作,您可以通过其他方式从 Crystal 获得您想要的。你能给你的问题提供更广泛的背景吗?你为什么要尝试做这些事情?
  • 1 在处理数据集(如在 R 或 Numpy 中)时,使用 Array 索引数组可能非常方便。 2 不想重复初始化哈希(通过键入所有键调用初始化)。

标签: crystal-lang splat


【解决方案1】:

Array 和 Hash 是动态扩展的容器,元素的数量可以在运行时改变,当你尝试 splat 时,数组可能是空的。

Tuple 和 NamedTuple 由固定数量的元素组成,这些元素在编译时是已知的,因此它们可以用于 splats。如果你的数据容器的格式没有改变,你可以使用 Tuple 和 NamedTuple 来代替。

ary = {"a", "b"}
h.values_at(*ary)

【讨论】:

  • 使用在运行时创建的 Array 索引 Array 或 Hash 的最佳方法是什么?
  • 什么意思?
  • @MikhailGordeev 我相信,无论如何,您都需要一个(命名)元组,这是设计使然。因此,最好在编译时更改代码以使用 (Named)Tuple 而不是 Array,如果将来您应该转换它。
【解决方案2】:

根据具体情况,第一个示例可能是不可能的。但是,如果元素的长度是固定的,您可以这样做:

h = {"a" => 1, "b" => 2, "c" => 3}
ary = ["a", "b"]
p h.values_at(*{String, String}.from(ary))

https://carc.in/#/r/3ootTuple.from

NamedTuple 支持同样的方法:

struct Point                                                                                                 
    def initialize(@x : Int32, @y : Int32)                                                                     
    end                                                                                                        
end
h = {"x" => 1, "y" => 2}

p Point.new(**{x: Int32, y: Int32}.from(h))

https://carc.in/#/r/3oovNamedTuple.from

这两者只是确保类型和在运行时手动分解结构的一些糖分,主要在您的数据来自外部来源(例如从 JSON 解析)时有用。

当然,在可能的情况下,首先创建和使用Tuple 而不是ArrayNamedTuple 而不是Hash 是首选。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2023-04-08
    • 2021-01-08
    • 1970-01-01
    • 2020-05-09
    • 2014-04-21
    • 2021-12-23
    相关资源
    最近更新 更多