Julia 模块中的 Expr eval 给出 UndefVarError

sob*_*sob 7 metaprogramming dataframe julia

我能够很好地运行以下代码,并且它提供了预期的结果:

\n
julia> using DataFrames, DataFramesMeta\n\njulia> expr = "2*:a+:b"\n"2*:a+:b"\n\njulia> df = DataFrame(a=[1,2],b=[3,4])\n2\xc3\x972 DataFrame\n Row \xe2\x94\x82 a      b     \n     \xe2\x94\x82 Int64  Int64 \n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n   1 \xe2\x94\x82     1      3\n   2 \xe2\x94\x82     2      4\n\njulia> eval(Meta.parse("@transform(df, " * join(collect(":res" => expr), " = ") * ")"))\n2\xc3\x973 DataFrame\n Row \xe2\x94\x82 a      b      res   \n     \xe2\x94\x82 Int64  Int64  Int64 \n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n   1 \xe2\x94\x82     1      3      5\n   2 \xe2\x94\x82     2      4      8\n\n
Run Code Online (Sandbox Code Playgroud)\n

然而,当在模块内完成时,这会失败。

\n
julia> module foo\n           using DataFrames, DataFramesMeta\n           function bar()\n               expr = "2*:a+:b"\n               df = DataFrame(a=[1,2],b=[3,4])\n               eval(Meta.parse("@transform(df, " * join(collect(":res" => expr), " = ") * ")"))\n           end\n       end\nMain.foo\n\njulia> foo.bar()\nERROR: UndefVarError: df not defined\nStacktrace:\n [1] top-level scope\n   @ ~/.julia/packages/DataFramesMeta/BkRtJ/src/macros.jl:1363\n [2] eval\n   @ ./boot.jl:368 [inlined]\n [3] eval\n   @ ./REPL[9]:1 [inlined]\n [4] bar()\n   @ Main.foo ./REPL[9]:6\n [5] top-level scope\n   @ REPL[10]:1\n
Run Code Online (Sandbox Code Playgroud)\n

我想这可能是范围问题,并试图通过使用foo.df而不是明确地df在函数调用中明确显示,但没有成功。

\n

有谁知道如何预防df这里被识别为已定义变量吗?

\n

Prz*_*fel 1

就像 Bogumil 所说的那样,eval完全看起来不像是编写代码的推荐方式。

\n

但是,如果您的目标是学习宏,那么这是正确的代码:

\n
module Foo2\n    using DataFrames, DataFramesMeta\n    function bar()\n        expr = "2*:a+:b"\n        df = DataFrame(a=[1,2],b=[3,4])\n        code = quote\n            @transform($df, :res = $(Meta.parse(expr)))\n        end\n        eval(code)\n    end\nend\n
Run Code Online (Sandbox Code Playgroud)\n

现在你可以运行:

\n
julia> Foo2.bar()\n2\xc3\x973 DataFrame\n Row \xe2\x94\x82 a      b      res\n     \xe2\x94\x82 Int64  Int64  Int64\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n   1 \xe2\x94\x82     1      3      5\n   2 \xe2\x94\x82     2      4      8\n
Run Code Online (Sandbox Code Playgroud)\n