如何使用 splat 运算符注释类型
How to annotate type using the splat operator
如何(是否可能)在使用 splat 运算符时注释参数类型?
f(x, y) = x^2 + y^2
vec = [1.0, 2.0, 'a']
f(vec[1:2]...)
如何在函数调用中注释 ...
的使用。还要注意 none 的宏来查看代码 (@code_llvm
, @code_lowered
, @code_native
, @code_typed
, @code_warntype
) 工作,所以它会使用 splat 时很难优化吗?
因为在上面的用例中,反射函数的宏版本似乎无法达到正确的参数类型,使用原始函数而不是宏,可能会有帮助:
f(x, y) = x^2 + y^2
vec = [1.0, 2.0, 'a']
@code_warntype(f(vec[1:2]...)) # => Nothing
code_warntype(f,map(typeof,vec[1:2]))
# Variables:
# x::Float64
# y::Float64
# .....
这个逻辑适用于所有反射宏,使用它们的变体函数和 (function, collection of types)
。
参考文献:
- 宏@code_warntype 具有函数变体:@code_warntype
- 宏的生成方式:macro generator
- Util 函数达到类型:gen_call_with_extracted_types
我想你的意思是这样的:
julia> foo(args::Float64...) = sum([x^2 for x in args])::Float64
foo (generic function with 1 method)
julia> foo(args::Vector{Float64}) = foo(args...)::Float64
foo (generic function with 2 methods)
julia> foo(args::Tuple{Vararg{Float64}}) = foo(args...)::Float64
foo (generic function with 3 methods)
julia> foo(2.0, 5.5, 7.0)
83.25
julia> v = Float64[2, 5.5, 7.0]
3-element Array{Float64,1}:
2.0
5.5
7.0
julia> foo(v)
83.25
julia> t = tuple(v...)
(2.0,5.5,7.0)
julia> foo(t)
83.25
我在几个地方放置了类型注释,因此您可以了解各种可能性。
julia> @which foo(2.0, 5.5, 7.0)
foo(args::Float64...) at none:1
julia> @which foo(v)
foo(args::Array{Float64,1}) at none:1
julia> @which foo(t)
foo(args::Tuple{Vararg{Float64}}) at none:1
@code_warntype
等
julia> @code_warntype foo(2.0, 5.5, 7.0)
Variables:
args::Tuple{Float64,Float64,Float64}
#s33::Int64
#s32::Int64
#s31::Int64
x::Float64
#s30::Int64
Body:
begin # none, line 1:
GenSym(1) = (Base.nfields)(args::Tuple{Float64,Float64,Float64})::Int64
0:
GenSym(3) = (top(ccall))(:jl_alloc_array_1d,(top(apply_type))(Base.Array,Float64,1)::Type{Array{Float64,1}},(top(svec))(Base.Any,Base.Int)::SimpleVector,Array{Flo
at64,1},0,GenSym(1),0)::Array{Float64,1}
#s33 = 1
#s32 = 1
#s31 = 0
unless (Base.box)(Base.Bool,(Base.not_int)(#s31::Int64 === GenSym(1)::Bool)::Any)::Bool goto 2
3:
#s31 = (Base.box)(Base.Int,(Base.add_int)(#s31::Int64,1)::Any)::Int64
GenSym(10) = (Base.getfield)(args::Tuple{Float64,Float64,Float64},#s32::Int64)::Float64
GenSym(11) = (Base.box)(Base.Int,(Base.add_int)(#s32::Int64,1)::Any)::Int64
#s30 = 1
GenSym(12) = GenSym(10)
GenSym(13) = (Base.box)(Base.Int,(Base.add_int)(1,1)::Any)::Int64
x = GenSym(12)
#s30 = GenSym(13)
GenSym(14) = GenSym(11)
GenSym(15) = (Base.box)(Base.Int,(Base.add_int)(2,1)::Any)::Int64
#s32 = GenSym(14)
#s30 = GenSym(15)
GenSym(4) = (Base.box)(Base.Float64,(Base.mul_float)(x::Float64,x::Float64)::Any)::Float64
$(Expr(:type_goto, 0, GenSym(4)))
$(Expr(:boundscheck, false))
(Base.arrayset)(GenSym(3),GenSym(4),#s33::Int64)::Array{Float64,1}
$(Expr(:boundscheck, :(Main.pop)))
#s33 = (Base.box)(Base.Int,(Base.add_int)(#s33::Int64,1)::Any)::Int64
4:
unless (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.not_int)(#s31::Int64 === GenSym(1)::Bool)::Any)::Bool)::Any)::Bool goto 3
2:
1:
GenSym(8) = GenSym(3)
return (Base._mapreduce)($(Expr(:new, :((top(getfield))(Base,:IdFun)::Type{Base.IdFun}))),$(Expr(:new, :((top(getfield))(Base,:AddFun)::Type{Base.AddFun}))),GenSy
m(8))::Float64
end::Float64
julia> @code_warntype foo(v)
Variables:
args::Array{Float64,1}
Body:
begin # none, line 1:
return (top(_apply))((top(getfield))(Main,:call)::F,Main.foo,args::Array{Float64,1})::Float64
end::Float64
julia> @code_warntype foo(t)
Variables:
args::Tuple{Float64,Float64,Float64}
Body:
begin # none, line 1:
return (Main.foo)((top(getfield))(args::Tuple{Float64,Float64,Float64},1)::Float64,(top(getfield))(args::Tuple{Float64,Float64,Float64},2)::Float64,(top(getfield))(args::Tuple{Float64,Float64,Float64},3)::Float64)::Float64
end::Float64
编辑: IJulia 笔记本,测试于 juliabox.org,Julia v0.4.1:
你也可以在调用函数的时候加上类型注解:
julia> @which foo(t::Tuple{Vararg{Float64}}...)
foo(args::Tuple{Vararg{Float64}}) at none:1
julia> @which foo(v::Vector{Float64}...)
foo(args::Array{Float64,1}) at none:1
如何(是否可能)在使用 splat 运算符时注释参数类型?
f(x, y) = x^2 + y^2
vec = [1.0, 2.0, 'a']
f(vec[1:2]...)
如何在函数调用中注释 ...
的使用。还要注意 none 的宏来查看代码 (@code_llvm
, @code_lowered
, @code_native
, @code_typed
, @code_warntype
) 工作,所以它会使用 splat 时很难优化吗?
因为在上面的用例中,反射函数的宏版本似乎无法达到正确的参数类型,使用原始函数而不是宏,可能会有帮助:
f(x, y) = x^2 + y^2
vec = [1.0, 2.0, 'a']
@code_warntype(f(vec[1:2]...)) # => Nothing
code_warntype(f,map(typeof,vec[1:2]))
# Variables:
# x::Float64
# y::Float64
# .....
这个逻辑适用于所有反射宏,使用它们的变体函数和 (function, collection of types)
。
参考文献:
- 宏@code_warntype 具有函数变体:@code_warntype
- 宏的生成方式:macro generator
- Util 函数达到类型:gen_call_with_extracted_types
我想你的意思是这样的:
julia> foo(args::Float64...) = sum([x^2 for x in args])::Float64
foo (generic function with 1 method)
julia> foo(args::Vector{Float64}) = foo(args...)::Float64
foo (generic function with 2 methods)
julia> foo(args::Tuple{Vararg{Float64}}) = foo(args...)::Float64
foo (generic function with 3 methods)
julia> foo(2.0, 5.5, 7.0)
83.25
julia> v = Float64[2, 5.5, 7.0]
3-element Array{Float64,1}:
2.0
5.5
7.0
julia> foo(v)
83.25
julia> t = tuple(v...)
(2.0,5.5,7.0)
julia> foo(t)
83.25
我在几个地方放置了类型注释,因此您可以了解各种可能性。
julia> @which foo(2.0, 5.5, 7.0)
foo(args::Float64...) at none:1
julia> @which foo(v)
foo(args::Array{Float64,1}) at none:1
julia> @which foo(t)
foo(args::Tuple{Vararg{Float64}}) at none:1
@code_warntype
等
julia> @code_warntype foo(2.0, 5.5, 7.0)
Variables:
args::Tuple{Float64,Float64,Float64}
#s33::Int64
#s32::Int64
#s31::Int64
x::Float64
#s30::Int64
Body:
begin # none, line 1:
GenSym(1) = (Base.nfields)(args::Tuple{Float64,Float64,Float64})::Int64
0:
GenSym(3) = (top(ccall))(:jl_alloc_array_1d,(top(apply_type))(Base.Array,Float64,1)::Type{Array{Float64,1}},(top(svec))(Base.Any,Base.Int)::SimpleVector,Array{Flo
at64,1},0,GenSym(1),0)::Array{Float64,1}
#s33 = 1
#s32 = 1
#s31 = 0
unless (Base.box)(Base.Bool,(Base.not_int)(#s31::Int64 === GenSym(1)::Bool)::Any)::Bool goto 2
3:
#s31 = (Base.box)(Base.Int,(Base.add_int)(#s31::Int64,1)::Any)::Int64
GenSym(10) = (Base.getfield)(args::Tuple{Float64,Float64,Float64},#s32::Int64)::Float64
GenSym(11) = (Base.box)(Base.Int,(Base.add_int)(#s32::Int64,1)::Any)::Int64
#s30 = 1
GenSym(12) = GenSym(10)
GenSym(13) = (Base.box)(Base.Int,(Base.add_int)(1,1)::Any)::Int64
x = GenSym(12)
#s30 = GenSym(13)
GenSym(14) = GenSym(11)
GenSym(15) = (Base.box)(Base.Int,(Base.add_int)(2,1)::Any)::Int64
#s32 = GenSym(14)
#s30 = GenSym(15)
GenSym(4) = (Base.box)(Base.Float64,(Base.mul_float)(x::Float64,x::Float64)::Any)::Float64
$(Expr(:type_goto, 0, GenSym(4)))
$(Expr(:boundscheck, false))
(Base.arrayset)(GenSym(3),GenSym(4),#s33::Int64)::Array{Float64,1}
$(Expr(:boundscheck, :(Main.pop)))
#s33 = (Base.box)(Base.Int,(Base.add_int)(#s33::Int64,1)::Any)::Int64
4:
unless (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.not_int)(#s31::Int64 === GenSym(1)::Bool)::Any)::Bool)::Any)::Bool goto 3
2:
1:
GenSym(8) = GenSym(3)
return (Base._mapreduce)($(Expr(:new, :((top(getfield))(Base,:IdFun)::Type{Base.IdFun}))),$(Expr(:new, :((top(getfield))(Base,:AddFun)::Type{Base.AddFun}))),GenSy
m(8))::Float64
end::Float64
julia> @code_warntype foo(v)
Variables:
args::Array{Float64,1}
Body:
begin # none, line 1:
return (top(_apply))((top(getfield))(Main,:call)::F,Main.foo,args::Array{Float64,1})::Float64
end::Float64
julia> @code_warntype foo(t)
Variables:
args::Tuple{Float64,Float64,Float64}
Body:
begin # none, line 1:
return (Main.foo)((top(getfield))(args::Tuple{Float64,Float64,Float64},1)::Float64,(top(getfield))(args::Tuple{Float64,Float64,Float64},2)::Float64,(top(getfield))(args::Tuple{Float64,Float64,Float64},3)::Float64)::Float64
end::Float64
编辑: IJulia 笔记本,测试于 juliabox.org,Julia v0.4.1:
你也可以在调用函数的时候加上类型注解:
julia> @which foo(t::Tuple{Vararg{Float64}}...)
foo(args::Tuple{Vararg{Float64}}) at none:1
julia> @which foo(v::Vector{Float64}...)
foo(args::Array{Float64,1}) at none:1