paiza.ioでelixir その188

# 概要
paiza.ioでelixirやってみた。
Macro使ってみた。

# サンプルコード

```
System.version()
|> IO.inspect

defmodule Example do
  defmacro macro_inspect(value) do
    IO.inspect(value)
    value
  end
  def fun_inspect(value) do
    IO.inspect(value)
    value
  end
end
defmodule MySigils do
  defmacro sigil_x(term, [?r]) do
    quote do
      unquote(term) |> String.reverse()
    end
  end
  defmacro sigil_x(term, _modifiers) do
    term
  end
  defmacro sigil_X(term, [?r]) do
    quote do
      unquote(term) |> String.reverse()
    end
  end
  defmacro sigil_X(term, _modifiers) do
    term
  end
end

defmodule Main do
    import Example
    macro_inspect(1 + 2)
    fun_inspect(1 + 2)
    import MySigils

    ~x(with #{"inter" <> "polation"})
    |> IO.inspect

    #=>"with interpolation"

    ~x(with #{"inter" <> "polation"})r
    |> IO.inspect

    #=>"noitalopretni htiw"

    ~X(without #{"interpolation"})
    |> IO.inspect

    #=>"without \#{"interpolation"}"

    ~X(without #{"interpolation"})r
    |> IO.inspect

    #=>"}\"noitalopretni\"{# tuohtiw"
end

siki = quote do
    var!(a) * var!(b)
end
|> IO.inspect

Code.eval_quoted(siki, [a: 3, b: 6], __ENV__)
|> IO.inspect

str = Macro.to_string(siki)
|> IO.inspect

{result, binding} = Code.eval_quoted(siki, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
|> IO.inspect

{result, binding} = Code.eval_quoted(siki, [a: 10, b: 2], __ENV__)
|> IO.inspect

quote do
    a + b
end
|> IO.inspect

defmodule Ma do
  defmacro mac(param) do
    IO.puts param
  end
end
#Ma.mac(1 + 2)
|> IO.inspect
# => {:{}, [line: 18], [1, 2, 3, 4, 5]}

Macro.camelize("foo_bar")
|> IO.inspect
#"FooBar"

Macro.camelize("API.V1")
|> IO.inspect
#"API.V1"
Macro.camelize("API_SPEC")
|> IO.inspect
#"API_SPEC"

Macro.decompose_call(quote(do: foo))
|> IO.inspect
#{:foo, []}

Macro.decompose_call(quote(do: foo()))
|> IO.inspect
#{:foo, []}

Macro.decompose_call(quote(do: foo(1, 2, 3)))
|> IO.inspect
#{:foo, [1, 2, 3]}

Macro.decompose_call(quote(do: Elixir.M.foo(1, 2, 3)))
|> IO.inspect
#{{:__aliases__, [], [:Elixir, :M]}, :foo, [1, 2, 3]}

Macro.decompose_call(quote(do: 42))
|> IO.inspect
#:error

Macro.decompose_call(quote(do: {:foo, [], []}))
|> IO.inspect
#:error

Macro.escape(:foo)
|> IO.inspect
#:foo

Macro.escape({:a, :b, :c})
|> IO.inspect
#{:{}, [], [:a, :b, :c]}

Macro.escape({:unquote, [], [1]}, unquote: true)
|> IO.inspect
#1

Macro.escape({:a, :b, :c})
|> IO.inspect
#{:{}, [], [:a, :b, :c]}
quote do: {:a, :b, :c}
|> IO.inspect
#{:{}, [], [:a, :b, :c]}

value = {:a, :b, :c}
Macro.escape(value)
|> IO.inspect
#{:{}, [], [:a, :b, :c]}

quote do: value
|> IO.inspect
#{:value, [], __MODULE__}

value = {:a, :b, :c}
quote do: unquote(value)
|> IO.inspect
#{:a, :b, :c}

#defmacro defmodule_with_length(name, do: block) do
#  length = length(Atom.to_charlist(name))
#  quote do
#    defmodule unquote(name) do
#      def name_length, do: unquote(length)
#      unquote(block)
#    end
#  end
#end
#defmodule_with_length My.Module do
#  def other_function, do: ...
#end

#alias MyHelpers, as: My

#defmodule_with_length My.Module do
#  def other_function, do: ...
#end

#defmacro defmodule_with_length(name, do: block) do
#  expanded = Macro.expand(name, __CALLER__)
#  length = length(Atom.to_charlist(expanded))
#  quote do
#    defmodule unquote(name) do
#      def name_length, do: unquote(length)
#      unquote(block)
#    end
#  end
#end

Macro.generate_arguments(2, __MODULE__)
|> IO.inspect
#[{:arg1, [], __MODULE__}, {:arg2, [], __MODULE__}]

[var1, var2] = Macro.generate_unique_arguments(2, __MODULE__)
#|> IO.inspect
{:arg1, [counter: c1], __MODULE__} = var1
{:arg2, [counter: c2], __MODULE__} = var2
is_integer(c1) and is_integer(c2)
|> IO.inspect
#true

Macro.quoted_literal?(quote(do: "foo"))
|> IO.inspect
#true
Macro.quoted_literal?(quote(do: {"foo", 1}))
|> IO.inspect
#true
Macro.quoted_literal?(quote(do: {"foo", 1, :baz}))
|> IO.inspect
#true
Macro.quoted_literal?(quote(do: %{foo: "bar"}))
|> IO.inspect
#true
Macro.quoted_literal?(quote(do: %URI{path: "/"}))
|> IO.inspect
#true
Macro.quoted_literal?(quote(do: URI.parse("/")))
|> IO.inspect
#false
Macro.quoted_literal?(quote(do: {foo, var}))
|> IO.inspect
#false

Macro.to_string(quote(do: foo.bar(1, 2, 3)))
|> IO.inspect
#"foo.bar(1, 2, 3)"

Macro.to_string(quote(do: 1 + 2), fn
  1, _string -> 
    "one"
  2, _string -> 
    "two"
  _ast, string -> 
    string
end)
|> IO.inspect
#"one + two"

Macro.underscore("FooBar")
|> IO.inspect
#"foo_bar"

Macro.underscore("Foo.Bar")
|> IO.inspect
#"foo/bar"

Macro.underscore(Foo.Bar)
|> IO.inspect
#"foo/bar"

Macro.underscore("SAPExample")
|> IO.inspect
#"sap_example"

Macro.camelize("sap_example")
|> IO.inspect
#"SapExample"

Macro.camelize("hello_10")
|> IO.inspect
#"Hello10"

Macro.unescape_string("example\\n")
|> IO.inspect
#"example\n"

#Macro.unescape_string("example\\n", &unescape_map(&1))

{:foo, [counter: c], __MODULE__} = Macro.unique_var(:foo, __MODULE__)
is_integer(c)
|> IO.inspect
#true

quote do: 100 |> div(5) |> div(2)
|> IO.inspect
#=> {:|>, _, [arg1, arg2]}

Macro.unpipe(quote do: 100 |> div(5) |> div(2))
|> IO.inspect
#=> [{100, 0}, {{:div, [], [5]}, 0}, {{:div, [], [2]}, 0}]

quoted = quote line: 10, do: sample()
|> IO.inspect
#{:sample, [line: 10], []}
Macro.update_meta(quoted, &Keyword.delete(&1, :line))
|> IO.inspect
#{:sample, [], []}

Macro.validate({:two_element, :tuple})
|> IO.inspect
#:ok
Macro.validate({:three, :element, :tuple})
|> IO.inspect
#{:error, {:three, :element, :tuple}}

Macro.validate([1, 2, 3])
|> IO.inspect
#:ok
Macro.validate([1, 2, 3, {4}])
|> IO.inspect
#{:error, {4}}

Macro.var(:foo, __MODULE__)
|> IO.inspect
#{:foo, [], __MODULE__}

Macro.var(:foo, nil)
|> IO.inspect
#{:foo, [], nil}





```
# 実行結果

```
"1.12.3"
{:+, [line: 35], [1, 2]}
3
"with interpolation"
"noitalopretni htiw"
"without \#{\"interpolation\"}"
"}\"noitalopretni\"{# tuohtiw"
{:*, [context: Elixir, import: Kernel],
 [
   {:var!, [context: Elixir, import: Kernel], [{:a, [], Elixir}]},
   {:var!, [context: Elixir, import: Kernel], [{:b, [], Elixir}]}
 ]}
{18, [b: 6, a: 3]}
"var!(a) * var!(b)"
{2, [b: 2, a: 1]}
{20, [b: 2, a: 10]}
{:+, [context: Elixir, import: Kernel], [{:a, [], Elixir}, {:b, [], Elixir}]}
{:module, Ma,
 <<70, 79, 82, 49, 0, 0, 5, 16, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 153,
   0, 0, 0, 16, 9, 69, 108, 105, 120, 105, 114, 46, 77, 97, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 7, 99, 111, 109, ...>>, {:mac, 1}}
"FooBar"
"API.V1"
"API_SPEC"
{:foo, []}
{:foo, []}
{:foo, [1, 2, 3]}
{{:__aliases__, [counter: -576460752303422783], [Elixir, :M]}, :foo, [1, 2, 3]}
:error
:error
:foo
{:{}, [], [:a, :b, :c]}
1
{:{}, [], [:a, :b, :c]}
{:{}, [], [:a, :b, :c]}
[{:arg1, [], nil}, {:arg2, [], nil}]
true
true
true
true
true
true
false
false
"foo.bar(1, 2, 3)"
"one + two"
"foo_bar"
"foo/bar"
"foo/bar"
"sap_example"
"SapExample"
"Hello10"
"example\n"
true
[{100, 0}, {{:div, [], [5]}, 0}, {{:div, [], [2]}, 0}]
{:|>, [context: Elixir, import: Kernel],
 [
   {:sample, [line: 10], []},
   {{:., [line: 10],
     [{:__aliases__, [line: 10, alias: false], [:IO]}, :inspect]},
    [no_parens: true, line: 10], []}
 ]}
:ok
{:error, {:three, :element, :tuple}}
:ok
{:error, {4}}
{:foo, [], nil}
{:foo, [], nil}


```

# 成果物

https://paiza.io/projects/P-N3SQnQb5u2KkSHQ2mUuw


以上。