对外部范围的理解失去输出类型

comprehension over external range loses output type

又是一个新手问题,我觉得这个区别很迷惑:

it = 1:3
typeof([i^2 for i in 1:3]) # Array{Int64,1}
typeof([i^2 for i in it])  # Array{Any,1}

为什么 运行ge 的定义位置很重要?

typeof([i^2 for i in it::UnitRange{Int64}]) 似乎给出了提示,this discussion 也是如此。但是,无论上述行为的原因如何,实际问题都是:我如何 specify/enforce 理解的输出类型?

编辑:一个更完整的例子说明了两个不同的问题,

# global namespace

nu1 = 0.5 + [0 ,1:3]
nu2 = 0.5 + (0:3)
typeof([besselj(_nu,[1,2]) for _nu in nu1]) # Any
typeof([besselj(_nu,[1,2]) for _nu in nu2]) # Any
typeof([besselj(_nu,[1,2]) for _nu in 0.5 + (0:3)]) # correct inference

# within a function

function rb()
  nu = 0.5 + [0 ,1:3]
  bj   = [besselj(_nu,[1,2]) for _nu in nu]
end

function rb2()
  nu = 0.5 + (0:3)
  bj   = [besselj(_nu,[1,2]) for _nu in nu]
end

typeof(rb()) # Any
typeof(rb2())# Correct inference

我首先在函数中遇到了问题,其中使用向量与 运行ge 会产生不同的输出类型,在尝试解决此问题时,我在全局命名空间和 运行 中进行了实验另一个问题...

考虑以下代码

it = 1:3
@show typeof([i^2 for i in 1:3])
@show typeof([i^2 for i in it])

function foo()
    it = 1:3
    @show typeof([i^2 for i in 1:3])
    @show typeof([i^2 for i in it])
end

foo()

产生

typeof($(Expr(:comprehension, :(i^2), :(i = 1:3)))) => Array{Int64,1}
typeof($(Expr(:comprehension, :(i^2), :(i = it)))) => Array{Any,1}
typeof($(Expr(:comprehension, :(i^2), :(i = 1:3)))) => Array{Int64,1}
typeof($(Expr(:comprehension, :(i^2), :(i = it)))) => Array{Int64,1}

基本上,类型推断在全局范围内要困难得多,而 Julia 主要依靠它。这通常不是问题,因为所有 "real" 代码的范围都很好并且在 REPL 中不是 运行。数组理解 can 有时会有类型推断问题,尽管通常有一些原因(即你 "comprehending" 上面的东西没有具体类型,或者你正在评估的函数内部理解不是类型稳定的)。你总是可以让 Julia 知道输出应该是什么类型,使用类型化向量的常用语法,即

it = 1:3
x = [i^2 for i in 1:3]
@show typeof(x)  # typeof(x) => Array{Int64,1}
y = Int[i^2 for i in it]
@show typeof(y)  # typeof(y) => Array{Int64,1}

但我不希望通常需要它。当然,有些人喜欢对他们的类型非常明确assertions/declarations,所以如果你想确定,你可以使用这个。