19-魔法印(Sigils)

    我们已经学习了Elixir提供的字符串(双引号包裹)和字符列表(单引号包裹)。
    但是对于Elixir中所有的文本描述型数据类型来说,这些只是冰山一角。其它的,
    例如原子也是一种文本描述型数据类型。

    Elixir的一个特点就是高可扩展性:开发者能够为特定的领域来扩展语言。
    计算机科学的领域已是如此广阔。几乎无法设计一门语言来涵盖所有范围。
    我们的打算是,与其创造出一种万能的语言,不如创造一种可扩展的语言,
    让开发者可以根据所从事的领域来对语言进行扩展。

    本章将讲述“魔法印(sigils)”,它是Elixir提供的处理文本描述型数据的一种机制。

    魔法印以波浪号(~)起头,后面跟着一个字母,然后是分隔符。最常用的魔法印是~r,
    代表:

    Elixir提供了Perl兼容的正则表达式(regex),由PCRE库实现。

    正则表达式支持修饰符(modifiers),例如i修饰符使该正则表达式无视大小写:

    1. iex> "HELLO" =~ ~r/hello/
    2. false
    3. iex> "HELLO" =~ ~r/hello/i
    4. true

    阅读获取关于其它修饰符的及其所支持的操作的更多信息。

    1. ~r/hello/
    2. ~r|hello|
    3. ~r"hello"
    4. ~r'hello'
    5. ~r(hello)
    6. ~r[hello]
    7. ~r{hello}
    8. ~r<hello>

    支持多种分隔符是因为在处理不同的魔法印的时候更加方便。
    比如,使用括号作为正则表达式的分隔符会让人困惑,分不清括号是正则模式的一部分还是别的什么。
    但是,括号对某些魔法印来说就很方便。

    19.2-字符串、字符列表和单词魔法印

    除了正则表达式,Elixir还提供了三种魔法印。

    魔法印~s 用来生成字符串,类似双引号的作用:

    1. iex> ~s(this is a string with "quotes")
    2. "this is a string with \"quotes\""

    通过这个例子可以看出,如果文本中有双引号,又不想逐个转义,可以用这种魔法印来包裹字符串。

    魔法印~c 用来生成字符列表:

    魔法印~w 用来生成单词,以空格分隔开:

    1. iex> ~w(foo bar bat)

    魔法印~w 还接受csa修饰符(分别代表字符列表,字符串和原子)
    来选择结果的类型:

    1. iex> ~w(foo bar bat)a
    2. [:foo, :bar, :bat]
    1. iex> ~s(String with escape codes \x26 interpolation)
    2. iex> ~S(String without escape codes and without #{interpolation})
    3. "String without escape codes and without \#{interpolation}"

    字符串和字符列表支持以下转义字符:

    • \” 表示一个双引号
    • \’ 表示一个单引号
    • \\ 表示一个反斜杠
    • \a 响铃
    • \b 退格
    • \d 删除
    • \e 退出
    • \f 换页
    • \n 新行
    • \r 换行
    • \s 空格
    • \t 水平制表符
    • \v 垂直制表符
    • \DDD, \DD, \D 八进制数字(如\377)
    • \xDD 十六进制数字(如\x13)
    • \x{D…} 多个十六进制字符的十六进制数(如\x{abc13}

    魔法印还支持多行文本(heredocs),使用的是三个双引号或单引号:

    最常见的有多行文本的魔法印就是写注释文档了。
    例如,如果你要在注释里写一些转义字符,这有可能会报错。

    1. @doc """
    2. Converts double-quotes to single-quotes.
    3. ## Examples
    4. iex> convert("\\\"foo\\\"")
    5. "'foo'"
    6. """

    使用~S,我们就可以避免问题:

    1. @doc ~S"""
    2. Converts double-quotes to single-quotes.
    3. ## Examples
    4. iex> convert("\"foo\"")
    5. "'foo'"
    6. """
    7. def convert(...)

    本章开头提到过,魔法印是可扩展的。事实上,魔法印~r/foo/i等于是
    用两个参数调用了函数sigil_r

    1. iex> sigil_r(<<"foo">>, 'i')
    2. ~r"foo"i

    就是说,我们可以通过该函数阅读魔法印~r的文档:

    我们也可以通过实现相应的函数来提供我们自己的魔法印。例如,我们来实现一个~i(N)魔法印,
    返回整数:

    1. iex> defmodule MySigils do
    2. ...> def sigil_i(string, []), do: String.to_integer(string)
    3. ...> end
    4. iex> import MySigils