Sal*_*apa 2 macros metaprogramming julia
我想重新定义或覆盖一些函数Base,而不是用户注意到这一点.我前一段时间发现了这个伎俩:
original_stderr = STDERR
redirect_stderr()
# code
redirect_stderr(original_stderr)
Run Code Online (Sandbox Code Playgroud)
这成了我的重复模式,所以我做了一个宏:
macro suppress_err(block)
quote
orig_err = STDERR
redirect_stderr()
val = $block
redirect_stderr(orig_err)
val
end
end
Run Code Online (Sandbox Code Playgroud)
但它从未像预期的那样表现(即使没有宏):
在Windows中:
julia> @suppress_err warn()
julia> @suppress_err error()
ERROR:
in error at error.jl:22
Run Code Online (Sandbox Code Playgroud)
适用于Linux的Windows子系统:
julia> @suppress_err warn()
[1] 17 abort (core dumped) julia
julia 7.69s user 2.36s system 106% cpu 9.441 total
Run Code Online (Sandbox Code Playgroud)
在Linux中:
julia> @suppress_err +(x, y) = x - y
ERROR: UndefVarError: #11#x not defined
in eval(::Module, ::Any) at ./boot.jl:234
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
Run Code Online (Sandbox Code Playgroud)
显然我正在做一些非常错误的事情,我应该采取哪些正确的方法解决这个问题?我应该在Julia存储库中提出问题吗?
我也试过close在两者上使用err_rd, err_wr = redirect_stderr(),然后重新定向到原来STDERR没有成功.
我已经使用我已经完成的工作制作了一个Suppressor包,因此您可以轻松地测试它:
Pkg.clone("https://github.com/Ismael-VC/Suppressor.jl")
Run Code Online (Sandbox Code Playgroud)
所有宏都具有相同的基本形式:
macro suppress_err(block)
quote
let
if ccall(:jl_generating_output, Cint, ()) == 0
ORIGINAL_STDERR = STDERR
err_rd, err_wr = redirect_stderr()
value = $(esc(block))
REDIRECTED_STDERR = STDERR
redirect_stderr(ORIGINAL_STDERR)
# This doesn't help:
# close(err_rd)
# close(err_wr)
return value
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
JuliaParser 您需要保留对原始返回值的引用redirect_stderr.它返回读取和写入结束,但是当存储写入结束时STDERR,读取结束不存在,因此GC可能决定将其删除.如果发生这种情况,它会在系统级别关闭,所以当julia尝试写入它时,它会收到该错误.
注意:下面的示例代码根据当前Suppressor.jl版本更新.
macro suppress_err(block)
quote
if ccall(:jl_generating_output, Cint, ()) == 0
ORIGINAL_STDERR = STDERR
err_rd, err_wr = redirect_stderr()
err_reader = @async readstring(err_rd)
value = $(esc(block))
redirect_stderr(ORIGINAL_STDERR)
close(err_wr)
return value
end
end
end
Run Code Online (Sandbox Code Playgroud)