JuliaDo函数的语法是如何工作的?
我在这里看到do语法可以用作编写map()函数的更方便的方法,但我不明白例如在链接的 julia 文档中显示的示例中:
open("outfile", "w") do io
write(io, data)
end
它适用于“打开”的以下函数定义
function open(f::Function, args...)
io = open(args...)
try
f(io)
finally
close(io)
end
end
如何在世界上没有的do传递io和write(io,data)到的实际功能open和f(io)?具有do块的函数是否必须具有相同的名称/被多次调度才能使do块工作?
回答
这是一个纯粹的句法转换。
func(x) do y
body
end
相当于
func(y -> body, x)
或者
tmp = y -> body
func(tmp, x)
如果你愿意,即do块定义了一个匿名函数,作为第一个参数传递。为此,当然,需要存在一种func具有匹配签名的方法,例如func(f::Function, ...) = ...(或简单地func(f, ...) = ...)。
您可以使用以下命令检查实际发生的情况Meta.@lower:
julia> Meta.@lower func(x) do y
print(y)
end
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ? $(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ? global var"#1#2"
? const var"#1#2"
? %3 = Core._structtype(Main, Symbol("#1#2"), Core.svec(), Core.svec(), false, 0)
? var"#1#2" = %3
? Core._setsuper!(var"#1#2", Core.Function)
? Core._typebody!(var"#1#2", Core.svec())
??? return nothing
)))
? %2 = Core.svec(var"#1#2", Core.Any)
? %3 = Core.svec()
? %4 = Core.svec(%2, %3, $(QuoteNode(:(#= REPL[1]:2 =#))))
? $(Expr(:method, false, :(%4), CodeInfo(
@ REPL[1]:2 within `none'
1 ? %1 = print(y)
??? return %1
)))
? #1 = %new(var"#1#2")
? %7 = #1
? %8 = func(%7, x)
??? return %8
))))
不幸的是,输出中包含匿名函数的实现细节:代码定义了一个新的 struct ( %3),%4使用do块体使其可调用 ( ) ,创建它的实例 ( %7),最后调用func(%7, x).