我有一个数组a
,我需要将其浅复制到数组b
中。
我应该使用
b = collect(a)
或
b = Array(a)
使用一个或另一个有哪些区别?
最佳答案
copy
是您要查找的内容:b = copy(a)
。
的确,您也可以使用collect
或Array
来完成这项工作,但有什么区别呢?在 Julia 中,有许多方便的辅助函数/宏,可以用来挖掘幕后发生的事情。
@which
、@edit
或 @less
经常用于确定在源代码中调用了哪个方法:
julia> a = rand(3,3)
julia> @which collect(a)
collect(itr) at array.jl:273
julia> @which Array(a)
(::Type{T}){T}(arg) at sysimg.jl:53
julia> @less collect(a)
collect(itr) = _collect(1:1 #= Array =#, itr, iteratoreltype(itr), iteratorsize(itr))
...
...
julia> @less Array(a)
(::Type{T}){T}(arg) = convert(T, arg)::T
...
...
这里的代码告诉我们 collect
将 a
(一个数组)视为一个迭代器,然后做了一些迭代器操作的事情,而不仅仅是一个浅拷贝。我推荐使用 Julia 的调试包 Gallium.jl
如果您想进一步深入研究代码。 Array(a)
只是做了一个比collect
更好的转换,但也不是必须的。 copy
的代码实际上非常底层:
copy{T<:Array}(a::T) = ccall(:jl_array_copy, Ref{T}, (Any,), a)
另一个强大的工具是@code_xxx
宏:
julia> @code_
@code_llvm @code_lowered @code_native @code_typed @code_warntype
例如,您可以检索并比较 LLVM-IR 代码以观察差异:
julia> @code_llvm Array(a)
define %jl_value_t* @julia_Type_73446(%jl_value_t*, %jl_value_t**, i32) #0 {
top:
%3 = alloca %jl_value_t**, align 8
store volatile %jl_value_t** %1, %jl_value_t*** %3, align 8
%4 = load %jl_value_t*, %jl_value_t** %1, align 8
ret %jl_value_t* %4
}
julia> @code_llvm copy(a)
define %jl_value_t* @julia_copy_73507(%jl_value_t*) #0 {
top:
%1 = call %jl_value_t* inttoptr (i64 4478340144 to %jl_value_t* (%jl_value_t*)*)(%jl_value_t* %0)
ret %jl_value_t* %1
}
@code_llvm collect(a)
将返回一堆代码,因为它不仅仅是一个简单的复制。我对 LLVM 不熟悉,所以我不能说更多。
关于arrays - 我应该使用 collect 还是 Array 在 Julia 中浅拷贝一个数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43186078/