Crystal如何将Array(T)转换为Array(T?)

问题描述 投票:0回答:1

我正在制作Serie-缺少值的不可变时间序列。但是没有空就不能初始化。

class Serie(T)
  def initialize(@array = Array(T?).new); end

  def self.[](*values : T); Serie(T).new values.to_a.as(Array(T?)) end
  def self.[](*values : T?); Serie(T).new values.to_a end
end

Serie[1, nil, 2] # Works    
Serie[1, 2]      # Throws an Error

此外,如果没有显式类型,也无法使用数组进行初始化,并且会引发错误。尽管似乎有足够的信息来推断类型。

Serie.new(Int32?)([1, nil, 2]) # Works
Serie.new([1, nil, 2])        # Throws an Error

P.S。

我正在使用Serie.self[...]对其进行初始化,您知道一种将其初始化为类似数组的对象Serie{1, 2}的方法,但是要避免添加<<方法,因为它是静态的不可变时间序列数据?

crystal-lang
1个回答
1
投票

[Array(T).new.as(Array(T?))无法工作,因为Array(T?)不是对Array(T)的有效限制(Crystal的泛型还不能表达协方差)。

为了从Array(T)转换为Array(T?),您实际上需要创建一个Array(T?)类型的新数组并将其复制过来。一种方法是values.map(&.as(T?))

((从技术上讲,您也可以使用不安全的类型强制转换来获取Array(T?)的实例,该实例指向与Array(T)相同的内存,因为二进制表示形式是相同的;但是当通过添加nil值时,它很容易中断nilable实例。)实际上不是真的,由于联合类型,二进制表示形式有所不同。

我正在使用Serie.self [...]进行初始化。您知道一种将其初始化为类似数组的对象Serie {1、2}的方法,但要避免添加<

添加self.[]方法可能是最好的解决方法。讨论如何将类似于数组的文字的实现更改为调用单个方法,而不是转换为<<中的一系列#5703调用。

© www.soinside.com 2019 - 2024. All rights reserved.