我正在按照Wikibook学习Julia,但我不明白为什么下面的两个命令会产生不同的结果:
julia> [1:2]
1-element Array{UnitRange{Int64},1}:
1:2
julia> Array[1:2]
1-element Array{Array,1}:
[1,2]
如果在Wikibook中有我没有看到的解释,我很抱歉,我简要地查看了一下,但没有找到。
Type[a] 运行 convert 函数来处理元素,Range 和 Array(collect)之间存在着简单的转换。所以 Array[1:2]
将 1:2
转换成一个数组,然后生成像那样的对象数组。这与为什么 Float64[1;2;3] 是一个 Float64 数组是相同的。
a:b
不是一个数组,它是一个 UnitRange
。为什么要为 A = a:b
创建一个数组呢?只需要两个数字就可以存储它,并且您可以基本免费地计算任何 i
的 A[i]
。使用数组将占用与 b-a
成比例的内存量,因此对于更大的数组,分配时间会很长,而分配 UnitRange
实际上是免费的。
在 Julia 中,这些类型被称为惰性迭代器。LinSpace 是另一个例子。另一组有趣的类型是特殊矩阵类型:为什么要使用多个数组来存储 Diagonal
?UniformScaling
操作符作为恒等矩阵,同时只存储一个值(它的比例),以使 A-kI
更高效。
由于 Julia 具有强大的类型系统,没有理由将所有这些东西都制作成数组。相反,您可以将它们制作成专门的类型,这些类型将像数组一样操作(*
、+
等)和索引,但实际上并不是数组。这将使它们占用更少的内存,并且更快。如果您需要数组,只需调用 collect(A)
或 full(A)
。
我意识到您发布了一些更具体的内容。原因在于 Array[1:2]
调用了数组的 getindex
函数。这个 getindex
函数对 Range
进行了特殊的分派,以便它“像被数组索引”一样运作(请参见前面的讨论)。所以这是“特别处理的”,但实际上它只是像其他函数一样分派来像数组一样运作。无论 A 是什么,[A]
都会给出一个 typeof(A)
数组,所以这里没有什么魔法。
1:2
是一个对象而不是数组。我不明白的是为什么Array[1:2]
似乎会扩展其参数。 - Jonathan Hgetindex
重载引起的。任何语言都有其特殊性,但这个问题很难理解;这也引出了一个问题,为什么A[1:2] == A[[1:2...]]
呢? - Jonathan HType[a]
在元素上运行 convert
,而在 Range
和 Array
(collect
) 之间有一个简单的转换。这就是为什么 Float64[1;2;3]
是一个 Float64
数组的原因:逐个元素进行转换。 - Chris Rackauckas
Array[[1:2]]
给出了另一个结果(一个包含数组和范围的数组),但这对我来说是有意义的。也许我没有理解的是为什么[ a:b ]
是特殊的? - Jonathan H