如何在第一次调用 Julia 函数时执行一些代码?

log*_*ick 2 julia

我有一个特定的用例,我希望一个函数在第一次调用时基本上提供警告以告诉用户一些信息。除了使用全局计数器并跟踪函数被调用的次数之外,我不知道如何检查这一点。关于特定 Julia 语法的任何想法都可以让我检查该函数是否是第一次被调用?

phi*_*ler 5

当您可以选择重写函数体时,以下是有关如何执行此操作的一些想法。 所有这些也可以通过编写一个相当简单的宏来执行相应的转换来实现。好吧,如果您想让顶级定义和​​本地定义正常工作,那么这并不是那么简单。

\n

(非)选项 1

\n

从概念上讲,您可以使用生成的函数来完成此操作,并且在您尝试时它大部分都会起作用:

\n
julia> @generated function dostuff(x)\n           @warn "You really shouldn\'t do stuff!"\n           return :(2x + 1)\n       end\ndostuff (generic function with 1 method)\n\njulia> dostuff(1)\n\xe2\x94\x8c Warning: You really shouldn\'t do stuff!\n\xe2\x94\x94 @ Main REPL[1]:2\n3\n\njulia> dostuff(1)\n3\n
Run Code Online (Sandbox Code Playgroud)\n

但是:不要。编译器可以自由选择何时调用“生成器”,并引用文档未定义这些副作用发生的确切时间、频率或次数。这不是一个好主意。

\n

@warn此外,是否会使用生成函数中允许的打印函数也是值得怀疑的。在早期的 Julias 中,使用println代替有时Core.println会在生成的函数中出错,因为前者修改了事件循环。

\n

选项2

\n

所以为了更好的东西。您可以通过将函数定义为 let 绑定变量的闭包来执行类似的操作,而不是使用全局计数器的想法:

\n
julia> let isfirstcall = Threads.Atomic{Bool}(true)\n           global function dostuff(x) \n               if Threads.atomic_xchg!(isfirstcall, false)\n                   @warn "You really shouldn\'t do stuff!"\n               end\n               return 2x + 1\n           end\n       end\ndostuff (generic function with 1 method)\n\njulia> dostuff(1)\n\xe2\x94\x8c Warning: You really shouldn\'t do stuff!\n\xe2\x94\x94 @ Main REPL[16]:4\n3\n\njulia> dostuff(1)\n3\n\njulia> isfirstcall\nERROR: UndefVarError: isfirstcall not defined\n
Run Code Online (Sandbox Code Playgroud)\n

我在这里选择使用原子只是为了好玩atomic_xchg!,但如果线程不是问题,那么普通的布尔值也可以。

\n

选项3

\n

另外,虽然可以避免,但如果你做得正确,全局变量也不会太糟糕。这意味着:将其设为const Ref. 并且(可选,但在本例中推荐),使用字符串var为其指定用户通常无法访问的名称:

\n
julia> const var"##isfirstcall" = Ref(true)\n\njulia> function dostuff(x)\n           if var"##isfirstcall"[]\n               @warn "You really shouldn\'t do stuff!"\n               var"##isfirstcall"[] = false\n           end\n           return 2x + 1\n       end\ndostuff (generic function with 1 method)\n\njulia> dostuff(1)\n\xe2\x94\x8c Warning: You really shouldn\'t do stuff!\n\xe2\x94\x94 @ Main REPL[22]:3\n3\n\njulia> dostuff(1)\n3\n
Run Code Online (Sandbox Code Playgroud)\n