我想在Elixir写一个字谜检查器。它需要2个单词,第一个是参考,第二个是作为第一个可能的anagram测试。
我试图用递归和模式匹配来编写它。我收到有关使用该错误的错误 in
保护条款中的操作员:
(ArgumentError)运算符的无效args,它需要编译
用于保护表达式时右侧的时间列表或范围
我不知道该怎么做才能解决它。这是代码(错误在第4个定义中):
defmodule MyAnagram do
def anagram?([], []), do: true
def anagram?([], word) do
IO.puts 'Not an anagram, the reference word does not contain enough letters'
false
end
def anagram?(reference, []) do
IO.puts 'Not an anagram, some letters remain in the reference word'
false
end
def anagram?(reference, [head | tail]) when head in reference do
anagram?(reference - head, tail)
end
def anagram?(_, [head | _]) do
IO.puts 'Not an anagram, #{head} is not in the reference word.'
false
end
end
这是由以下代码引起的(如您所示):
def anagram?(reference, [head | tail]) when head in reference do
anagram?(reference - head, tail)
end
你可以找到的定义 in
宏 在源代码中,但为了方便起见,我在这里复制了它 - 它还包含文档中的以下内容:
逆天
该 in
运算符可以在保护条款中使用
因为右侧是范围或列表。在这种情况下,Elixir
将运算符扩展为有效的保护表达式。例如:
when x in [1, 2, 3]
翻译为:
when x === 1 or x === 2 or x === 3
定义宏的代码:
defmacro left in right do
in_module? = (__CALLER__.context == nil)
right = case bootstraped?(Macro) and not in_module? do
true -> Macro.expand(right, __CALLER__)
false -> right
end
case right do
_ when in_module? ->
quote do: Elixir.Enum.member?(unquote(right), unquote(left))
[] ->
false
[h|t] ->
:lists.foldr(fn x, acc ->
quote do
unquote(comp(left, x)) or unquote(acc)
end
end, comp(left, h), t)
{:%{}, [], [__struct__: Elixir.Range, first: first, last: last]} ->
in_range(left, Macro.expand(first, __CALLER__), Macro.expand(last, __CALLER__))
_ ->
raise ArgumentError, <<"invalid args for operator in, it expects a compile time list ",
"or range on the right side when used in guard expressions, got: ",
Macro.to_string(right) :: binary>>
end
end
您的代码块正在命中case语句的最后一部分,因为在编译时无法保证您的变量 reference
是类型 list
(要么 range
。)
您可以通过调用以下内容查看传递给宏的值:
iex(2)> quote do: head in reference
{:in, [context: Elixir, import: Kernel],
[{:head, [], Elixir}, {:reference, [], Elixir}]}
在这里,原子 :reference
正在传递给 in
宏,它与之前的任何条款都不匹配,所以它落到了 _
子句(引发错误。)
要解决此问题,您需要将最后两个子句合并为一个函数:
def anagram?(reference, [head | tail]) do
case head in reference do
false ->
IO.puts 'Not an anagram, #{head} is not in the reference word.'
false
true ->
anagram?(reference - head, tail)
end
end
值得注意的是,您可能想要使用 "strings"
代替 'char_lists'
http://elixir-lang.org/getting-started/binaries-strings-and-char-lists.html#char-lists
另一件事是打电话 reference - head
将无法工作(它将提出一个 ArithmeticError
)。你可能想看一下 List.delete / 2 从列表中删除项目。
这是由以下代码引起的(如您所示):
def anagram?(reference, [head | tail]) when head in reference do
anagram?(reference - head, tail)
end
你可以找到的定义 in
宏 在源代码中,但为了方便起见,我在这里复制了它 - 它还包含文档中的以下内容:
逆天
该 in
运算符可以在保护条款中使用
因为右侧是范围或列表。在这种情况下,Elixir
将运算符扩展为有效的保护表达式。例如:
when x in [1, 2, 3]
翻译为:
when x === 1 or x === 2 or x === 3
定义宏的代码:
defmacro left in right do
in_module? = (__CALLER__.context == nil)
right = case bootstraped?(Macro) and not in_module? do
true -> Macro.expand(right, __CALLER__)
false -> right
end
case right do
_ when in_module? ->
quote do: Elixir.Enum.member?(unquote(right), unquote(left))
[] ->
false
[h|t] ->
:lists.foldr(fn x, acc ->
quote do
unquote(comp(left, x)) or unquote(acc)
end
end, comp(left, h), t)
{:%{}, [], [__struct__: Elixir.Range, first: first, last: last]} ->
in_range(left, Macro.expand(first, __CALLER__), Macro.expand(last, __CALLER__))
_ ->
raise ArgumentError, <<"invalid args for operator in, it expects a compile time list ",
"or range on the right side when used in guard expressions, got: ",
Macro.to_string(right) :: binary>>
end
end
您的代码块正在命中case语句的最后一部分,因为在编译时无法保证您的变量 reference
是类型 list
(要么 range
。)
您可以通过调用以下内容查看传递给宏的值:
iex(2)> quote do: head in reference
{:in, [context: Elixir, import: Kernel],
[{:head, [], Elixir}, {:reference, [], Elixir}]}
在这里,原子 :reference
正在传递给 in
宏,它与之前的任何条款都不匹配,所以它落到了 _
子句(引发错误。)
要解决此问题,您需要将最后两个子句合并为一个函数:
def anagram?(reference, [head | tail]) do
case head in reference do
false ->
IO.puts 'Not an anagram, #{head} is not in the reference word.'
false
true ->
anagram?(reference - head, tail)
end
end
值得注意的是,您可能想要使用 "strings"
代替 'char_lists'
http://elixir-lang.org/getting-started/binaries-strings-and-char-lists.html#char-lists
另一件事是打电话 reference - head
将无法工作(它将提出一个 ArithmeticError
)。你可能想看一下 List.delete / 2 从列表中删除项目。