julia - Julia 中推断的类型差异
问题描述
我正在尝试学习来自 Python 的 Julia,我在exercism.io上遇到了一段有趣的代码。用户做了一个优雅的技巧来创建包含函数的元组,因为它们是 Julia 中的一等对象。以此为基础,我想尝试一些东西。
假设我有一个列表:
my_list = zip(0:3, ["wink", "double blink", "close your eyes", "jump"]) |> collect
我想创建一个由 2 元素元组组成的列表,其中第二个元素是一个函数:
codes = [(i, x -> push!(x,j)) for (i,j) in my_list]
append!(codes, (4, reverse!))
代码无法运行。检查 REPL 中的签名,我意识到上面的第一行生成了一个带有签名的列表:4-element Array{Tuple{Int64,var"#68#70"{String}},1}:
而如果我像链接代码中那样手动执行该过程:
codes =
[ (0, i -> push!(i, "wink"))
, (1, i -> push!(i, "double blink"))
, (2, i -> push!(i, "close your eyes"))
, (3, i -> push!(i, "jump"))
, (4, reverse!)]
我得到了正确的类型:5-element Array{Tuple{Int64,Function},1}
. 我无法理解差异以及为什么我尝试做的不是有效代码。
解决方案
首先请注意,您不应该push!
在append!
向量末尾添加一个元素(append!
将集合的元素附加到另一个集合)。现在我将集中讨论主要问题,假设您会push!
在代码中使用。
的所有元素code
具有相同的类型:
julia> typeof.(codes)
4-element Array{DataType,1}:
Tuple{Int64,var"#4#6"{String}}
Tuple{Int64,var"#4#6"{String}}
Tuple{Int64,var"#4#6"{String}}
Tuple{Int64,var"#4#6"{String}}
julia> unique(typeof.(codes))
1-element Array{DataType,1}:
Tuple{Int64,var"#4#6"{String}}
甚至更多 - 这种类型是具体的:
julia> isconcretetype.(typeof.(codes))
4-element BitArray{1}:
1
1
1
1
(这意味着事情将变得稳定且快速,这很好)
在这种情况下,理解将这种类型设置为eltype
结果向量。
问题是(4, reverse!)
元组有不同的类型:
julia> typeof((4, reverse!))
Tuple{Int64,typeof(reverse!)}
所以你不能将它添加到codes
向量中,即:
julia> push!(codes, (4, reverse!))
ERROR: MethodError: Cannot `convert` an object of type typeof(reverse!) to an object of type var"#4#6"{String}
现在怎么解决?像这样创建它时设置一个适当eltype
的向量:codes
julia> codes = Tuple{Int, Function}[(i, x -> push!(x,j)) for (i,j) in my_list]
4-element Array{Tuple{Int64,Function},1}:
(0, var"#7#8"{String}("wink"))
(1, var"#7#8"{String}("double blink"))
(2, var"#7#8"{String}("close your eyes"))
(3, var"#7#8"{String}("jump"))
julia> push!(codes, (4, reverse!))
5-element Array{Tuple{Int64,Function},1}:
(0, var"#7#8"{String}("wink"))
(1, var"#7#8"{String}("double blink"))
(2, var"#7#8"{String}("close your eyes"))
(3, var"#7#8"{String}("jump"))
(4, reverse!)
一切都会按预期工作。
让我举一个同样问题的更简单的例子,让问题更清晰可见:
julia> x = [i for i in 1:3]
3-element Array{Int64,1}:
1
2
3
julia> eltype(x)
Int64
julia> push!(x, 1.5)
ERROR: InexactError: Int64(1.5)
Stacktrace:
[1] Int64 at ./float.jl:710 [inlined]
[2] convert at ./number.jl:7 [inlined]
[3] push!(::Array{Int64,1}, ::Float64) at ./array.jl:913
[4] top-level scope at REPL[55]:1
julia> x = Float64[i for i in 1:3]
3-element Array{Float64,1}:
1.0
2.0
3.0
julia> push!(x, 1.5)
4-element Array{Float64,1}:
1.0
2.0
3.0
1.5
并且append!
会像这样工作(继续上一个示例):
julia> append!(x, [2.5, 3.5])
6-element Array{Float64,1}:
1.0
2.0
3.0
1.5
2.5
3.5
推荐阅读
- c# - Dapper.Contrib 和 MiniProfiler (for MySql) 集成问题
- jms - IIB 应用程序 Windows 服务器中获取 JNDI 管理对象 MQ 失败
- javascript - angular1.x指令中的单引号内的双引号不起作用
- windows - BATCH - 如何从多行命令输出中仅获取一行
- javascript - 通过创建新的构造函数来拦截构造函数
- javascript - 使用 Slick Scroller Carousel 隐藏自定义按钮
- c++ - 一键“输入”怎么办?
- arrays - 检查对象数组php laravel的重复条目
- sql-server - TSQL:变量二进制文件的异或
- meteor - 流星中mqtt经纪人之间的桥接