在 Crystal 中从生成块中进行类型优化
Type refinement in Crystal from yielding blocks
我正在使用 Enumerable#select(&block) 尝试使用 arr.select { |el| el.is_a?(Bar) }
将数组优化为特定类型的元素,但那没有用。
然后我看到了Enumerable#select(type) method, and that worked: https://play.crystal-lang.org/#/r/7v05
但我注意到这两个定义在我的案例中非常相似。
def select(&block : T ->)
ary = [] of T
each { |e| ary << e if yield e }
ary
end
def select(type : U.class) forall U
ary = [] of U
each { |e| ary << e if e.is_a?(U) }
ary
end
有没有办法让编译器知道 select 块正在细化元素的类型(也许通过某种方式向块添加类型)?还是编译器不知道该块断言了什么?
这里的问题是需要使用正确的类型创建数组。所以这两种方式的核心区别在于:
ary = [] of T
其中 T
是您调用 select 的 Enumerable
的类型参数,而
ary = [] of U
其中 U
是此方法特定的类型参数 (forall U
)。
因此,要执行您想要的操作,我们需要知道该块正在过滤元素,但这绝不是在块类型中编码的。它只有一个参数类型列表和一个 return 类型。然而,我们当然可以将这两种方法组合成类似的东西:
module Enumerable(T)
def select(type : U.class) forall U
ary = [] of U
each { |e| ary << e if yield e if e.is_a? U }
ary
end
end
我正在使用 Enumerable#select(&block) 尝试使用 arr.select { |el| el.is_a?(Bar) }
将数组优化为特定类型的元素,但那没有用。
然后我看到了Enumerable#select(type) method, and that worked: https://play.crystal-lang.org/#/r/7v05
但我注意到这两个定义在我的案例中非常相似。
def select(&block : T ->)
ary = [] of T
each { |e| ary << e if yield e }
ary
end
def select(type : U.class) forall U
ary = [] of U
each { |e| ary << e if e.is_a?(U) }
ary
end
有没有办法让编译器知道 select 块正在细化元素的类型(也许通过某种方式向块添加类型)?还是编译器不知道该块断言了什么?
这里的问题是需要使用正确的类型创建数组。所以这两种方式的核心区别在于:
ary = [] of T
其中 T
是您调用 select 的 Enumerable
的类型参数,而
ary = [] of U
其中 U
是此方法特定的类型参数 (forall U
)。
因此,要执行您想要的操作,我们需要知道该块正在过滤元素,但这绝不是在块类型中编码的。它只有一个参数类型列表和一个 return 类型。然而,我们当然可以将这两种方法组合成类似的东西:
module Enumerable(T)
def select(type : U.class) forall U
ary = [] of U
each { |e| ary << e if yield e if e.is_a? U }
ary
end
end