スポンサーリンク

2015年8月31日

[Elixir]自作マクロでdo~end記述をできるようにする

とある錬金術師の万能薬(Elixir)

Goal

自作マクロでdo~end記述を可能にする。

Dev-Environment

OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4

Wait a minute

ふと思ったんです。
自分で定義するマクロで、
do~endの記述をできるようにするには・・・どうしたらいいのか?
以下のような記述がしたい。
macro_name do
  関数や処理
end

Index

do ~ end in your own macro
|> Create example
|> Let’s run!
|> Extra

Create example

まずは簡単な例を作成します。
どうやってやろうかと思いましたが・・・
if文でやってんだから、
if/2マクロをコピペして真似ればできるんじゃね?

Example:

defmodule Sample do
  defmacro hoge(clauses) do
    do_clause = Keyword.get(clauses, :do, nil)

    quote do
      IO.puts unquote(do_clause)
    end
  end
end
if/2マクロのdoに該当する部分だけコピペしてきた。
ただ、do部分を受け取って、内容を表示するだけのマクロ。

Let’s run!

それでは使ってみます。

Result:

iex> require Sample
nil
iex> Sample.hoge do
...>   "do block"
...> end
do block
:ok
やった!
成功です。

Extra

do以外にもできるのかなと思いやってみました。
(無理だと思いますが・・・一応)

Example:

defmodule Sample do
  defmacro hoge(clauses) do
    foo_clause = Keyword.get(clauses, :foo, nil)
    bar_clause = Keyword.get(clauses, :bar, nil)

    quote do
      IO.puts unquote(foo_clause)
      IO.puts unquote(bar_clause)
    end
  end
end

Result:

iex> Sample.hoge foo
** (FunctionClauseError) no function clause matching in Keyword.get/3
    (elixir) lib/keyword.ex:118: Keyword.get({:foo, [line: 4], nil}, :foo, nil)
             expanding macro: Sample.hoge/1
             iex:4: (file)
iex> Sample.hoge foo: "foo", bar: "bar"
foo
bar
:ok
当然ですが、できませんね。

Speaking to oneself

大した内容ではなかったですよね・・・
if、unlessをやった時に検証しておけば良かったのですが、
その時は意識が向いていませんでした。
なので、今回実施することとなりました。
何にせよ、Elixirすげぇな!!(信仰)

Bibliography

人気の投稿