【问题标题】:Elixir Operator Overloading: Defining an exclusive range using MacrosElixir 运算符重载:使用宏定义独占范围
【发布时间】:2018-01-01 10:57:18
【问题描述】:

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

所以,我查找了the definition of ..,因为... 的功能当然会非常相似。

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

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

== 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

我做错了什么?

【问题讨论】:

    标签: macros operator-overloading elixir


    【解决方案1】:

    您可以在 Elixir 中定义的中缀运算符数量有限:

    \\, <-, |, ~>>, <<~, ~>, <~, <~>, <|>, <<<, >>>, |||, &&&, and ^^^
    

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

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

    来自评论:

    |||&amp;&amp;&amp;^^^&lt;&lt;&lt;&gt;&gt;&gt;~~~ 默认情况下不会被导入,但它们是默认 Elixir 标准库的 Bitwise 模块的一部分。

    更多详情请见http://www.rodneyfolz.com/custom-infix-functions-in-elixir/

    【讨论】:

    • 让我补充一点,|||&amp;&amp;&amp;^^^&lt;&lt;&lt;&gt;&gt;&gt;~~~ 默认情况下不是导入的,而是默认 Elixir 的一部分标准库的Bitwise 模块。 (它们分别是按位或、与、异或、左移、右移和非)。所以最后只有\\ (也用于在函数子句中指定“默认”参数)、&lt;-(也用于理解内)和~&gt;&lt;~~&gt;&gt;&lt;&lt;~&lt;~&gt;&lt;|&gt; 保留。
    • 在上一个列表中我错过了|,它是可覆盖的,但已经在列表中使用来构造它们/模式匹配它们
    • 有关运算符的完整列表及其用途,请参阅gist.github.com/Qqwy/3066910db6bf9adcf91b8c5e99148c85
    猜你喜欢
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    • 2011-11-04
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多