Sigil大好き!一番好きな機能です。

  • 12
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Elixirには、Rubyなどの言語に見られるような %w(...) という記法が存在する。Elixirのドキュメントではそれを「Sigil」と呼んでいる。

%w(foo bar 123)
#=> ["foo", "bar", "123"]

ドキュメントにある通り以下の4つがデフォルトで定義済み。

  • %c and %C - Returns a char list;
  • %r and %R - Returns a regular expression;
  • %s and %S - Returns a string;
  • %w and %W - Returns a list of "words" split by whitespace;

また、Rubyの同様の表記と違い、接尾辞を指定できる。「modifier」と呼ばれる。無いものを指定すると例外。

%w(foo bar 123)a
#=> [:foo, :bar, :"123"]
%w(foo bar 123)z
# ** (ArgumentError) modifier must be one of: s, a, c
#    /private/tmp/elixir-s8oh/elixir-0.11.2/lib/elixir/lib/kernel.ex:3624: Kernel.split_words/2
#    iex:13: Kernel.sigil_w/2

このSigil記法、最終的にはsigil_*という名前の関数またはマクロが呼ばれることになるので、

%p()
# ** (RuntimeError) undefined function: sigil_p/2

このような名前の関数もしくはマクロを定義してあげると、独自のSigilを定義できる。

defmodule MySigil do
  def sigil_p(string, []) do
    IO.inspect(string)
  end
end

import MySigil
%p(Hello!)
#=> "Hello!"

この際sigil_p/2になるように定義すること。2番目の引数にはもちろんmodifierが入ってくる。

以下はSigilの内容のmd5ハッシュを出すサンプル。

defmodule Crypto do
  def to_md5(str) do
    Enum.join(
      Enum.map(
        bitstring_to_list(:crypto.hash :md5, str),
        fn(x) -> String.rjust(integer_to_binary(x, 16), 2, ?0) end
      )
    )
  end

  def sigil_m(string, []) do
    to_md5(string)
  end
end

import Crypto

%m'''
foo
bar
baz
'''
#=> "268A5059001855FEF30B4F95F82044ED"

Enjoy Sigiling!

次回はさっちゃんさんです!!