3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【メモ】juliaの@doc, @eval, @showの用例

Posted at

juliaのマクロについて

マクロとはメタプログラミングのことであり、プログラミングをプログラミングするみたいな感じである。
本記事はいくつかのマクロの例を実行してみることで、それらの理解を深めることが目的です。

なお、juliaのメタプログラミンのドキュメントに詳細が載っています。

@doc

@docは、何か値と紐づいたストリングを返すマクロである。

@docのコードを簡単な例で確認する。なお、SciPy.jlのsrcに出てくる@docに関するコードを参照しています。https://github.com/AtsushiSakai/SciPy.jl/blob/master/src/util.jl

@doc "hogehoge" g = sin(1) # g

実行

g #0.8414709848078965
@eval g #上と同じ
@doc g #hogehoge

ここで、@docをしたときに、裏でどのように実行されているかをみるには以下を実行する

@macroexpand @doc g
# :((Base.Docs.doc)((Base.Docs.Binding)(Main, :g)))

実際に、以下を実行すると@doc g と同じ結果が返ってくることがわかる。

eval(:((Base.Docs.doc)((Base.Docs.Binding)(Main, :g))))

この例を通して、@docによって、g(ここではsin関数)に紐づいた"hogehoge"という文字列を返すことがわかった。

@show

これは、よく使う人も多いかもしれないが、printlnの強化版みたいなイメージである
先ほどの続きで確かめる。

@macroexpand g # :g
eval(:g) # 0.8414709848078965
@show g
# g = 0.8414709848078965
# 0.8414709848078965
@macroexpand @show g

@macroexpandを使えば、@showがどのようなコードなのかみることができ、確かにprintlnとvalueを返していることがなんとなくわかる。

quote
    Base.println("g = ", Base.repr(begin
                #= show.jl:1047 =#
                local var"#30#value" = g
            end))
    var"#30#value"
end

@eval

与えられた関数とその引数を与えると、評価してくれるマクロになる。

a = zeros(4)

for (i, f) in enumerate([:sin, :cos, :tan, :log])
       @eval $a[$i] = $(f)(1)
       end

@assert a == [sin(1), cos(1), tan(1), log(1)]

b = zeros(4)
for (i, f) in enumerate([:sin, :cos, :tan, :log])
       @eval $b[$i] = $(f)($i)
       end

@assert b == [sin(1), cos(2), tan(3), log(4)] #OK
@assert b == [sin(1), cos(2), tan(3), log(100)] "NOOOOOO!" #これはエラー

おまけ:Exprとeval()

Meta.parse("1+1") # :(1 + 1)
Meta.parse("1+1") |> typeof # Expr
ex = :(1+1)
ex |> dump # データ型の構造を取得

結果

Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Int64 1
    3: Int64 1

ex.args, ex.headを実行すると、それぞれの値をとってこれる。

ここでExprの働きを詳しくみる。

Expr(:call, :+, 1,2,3) #:(1 + 2 + 3)

Expr(:call, :+, 1,2,3) == :(1+2+3) #と同じ

Expr(:call, :+, 1,2,3) == :(1+2+3) == Meta.parse("1+2+3") #と同じ

最後にexのargsの値を変更することも可能である

ex.args[end] = -1
ex # :(1 + -1)

eval(ex) #0

Expr は関数 eval() で評価することができる

まとめ

juliaのいろいろなマクロの例を見て理解を深めることができた。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?