函数的 Julia Do 语法是如何工作的?

How does the Julia Do Syntax for functions work?

我已经看到 here do 语法可以用作编写 map() 函数的更方便的方法,但我不明白例如在链接的 julia 文档中显示的示例中:

open("outfile", "w") do io
    write(io, data)
end

适用于 'open'

的以下函数定义
function open(f::Function, args...)
    io = open(args...)
    try
        f(io)
    finally
        close(io)
    end
end

do 究竟如何将 iowrite(io,data) 传递给 openf(io) 的实际功能? do 块的函数是否必须具有相同的 name/be 多分派才能使 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
))))

不幸的是,输出是匿名函数的实现细节的乱码:代码定义了一个新结构 (%3),使用 [= 的主体使其可调用 (%4) 14=] 块,创建它的一个实例 (%7),最后调用 func(%7, x).

如果它对任何人有帮助,我还通过摆弄@fredrikekre 通过这个例子写的一般内容发现:

function func(blah::Function,baz,foo)
   blah([baz,foo])
End

您可以将其称为以下任何一种

func("a", "b") do zzz
   vcat(uppercase.(zzz),"C")
end

func(zzz->vcat(uppercase.(zzz),"C"),"a", "b")

两者产生相同的输出

3-element Vector{String}:
 "A"
 "B"
 "C"