Elixir Operator重载:使用宏定义独占范围

Qqw*_*qwy 2 macros operator-overloading elixir

为了更好地理解Elixir语言,我想尝试通过添加一个独有的范围运算符来进行运算符重载....例如:1...10然后创建一个从1到10但不包括10的范围.(例如1...10 == 1..9)

所以,我查了一下定义..,因为...当然功能非常相似.

Mmy模块然后变成:

defmodule Sequences.Ranges do

  defmacro first ... last do
    case is_float(first) or is_float(last) or
         is_atom(first) or is_atom(last) or
         is_binary(first) or is_binary(last) or
         is_list(first) or is_list(last) do
      true ->
        raise ArgumentError,
          "ranges (first...last) expect both sides to be integers, " <>
          "got: #{Macro.to_string({:"Sequences.Ranges...", [], [first, last]})}"
      false ->
        case __CALLER__.context do
          nil -> quote do: Elixir.Range.new(unquote(first), unquote(last-1))
          _   -> {:%{}, [], [__struct__: Elixir.Range, first: first, last: (last-1)]}
        end
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

但是,在编译此模块时,我收到以下错误:

== Compilation error on file lib/sequences/ranges.ex ==
** (CompileError) lib/sequences/ranges.ex:6: cannot invoke local .../1 inside match
    (stdlib) lists.erl:1353: :lists.mapfoldl/3
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Cod*_*nis 5

在Elixir中只能定义有限数量的中缀运算符:

\\, <-, |, ~>>, <<~, ~>, <~, <~>, <|>, <<<, >>>, |||, &&&, and ^^^
Run Code Online (Sandbox Code Playgroud)

它们在解析器中预定义,但未实现(或者至少默认情况下不导入).这使它们可用于自定义实现,但除非您修改并重新编译Elixir本身,否则无法创建自己的添加到此列表.

... 不是其中之一,所以它不会起作用.

来自评论:

|||,&&&,^^^,<<<,>>>~~~不是默认导入,但默认的药剂标准库的一部分Bitwise模块.

有关详细信息,请参阅http://www.rodneyfolz.com/custom-infix-functions-in-elixir/.

  • 让我补充一下,默认情况下不导入`|||`,`&amp;&amp;&amp;`,`^^^`,`&lt;&lt;&lt;`,`&gt;&gt;&gt;`和`~~~`,但它们是默认Elixir标准库的“按位”模块。(它们分别是按位或,或xor,是左移,右移而不是)。所以最后只有`\\`(也用于在函数子句中指定'default'参数),`&lt;-`(也用于内部理解)和`〜&gt;`,`&lt;〜` ,`〜&gt;&gt;`,`&lt;&lt;〜`,`&lt;〜&gt;`,`&lt;|&gt;`保留。 (2认同)
  • 有关运算符及其用途的完整列表,请参阅 https://gist.github.com/Qqwy/3066910db6bf9adcf91b8c5e99148c85 (2认同)