【问题标题】:Why do I receive a FunctionClauseError ("no function clause matching") in this Elixir program, translated from Erlang? [closed]为什么我在这个从 Erlang 翻译的 Elixir 程序中收到 FunctionClauseError(“没有函数子句匹配”)? [关闭]
【发布时间】:2015-06-12 22:26:37
【问题描述】:

**所以,我以前使用过 Erlang,并且对它非常满意。我只是想学习 Elixir。

我最近试图将一个“懒惰的餐饮服务商”示例翻译成 elixir,但我很困惑为什么它要么无法编译,要么编译时出现警告并且无法正常工作。我在这里错过了什么;有任何想法吗? erlang代码和'run'如下:**

jps@GRASSKEET ~/dev/erlang
$ cat cater.erl

    -module(cater).
    -export([cater/1]).
    cater(0) -> 1;
    cater(N) when N>0 -> N + cater(N-1).

jps@GRASSKEET ~/dev/erlang
$ erl
Eshell V6.3  (abort with ^G)
1> c("cater.erl").
{ok,cater}
2> cater:cater(10).
56
3>*

当我这样写 Cater.ex 时,它会出现一个对我来说没有意义的错误:

jps@GRASSKEET ~/dev/elix
$ cat Cater.ex

    defmodule Cater do
      def cut(0), do: 1
      def cut(N) when N>0, do: N + cut(N-1)
    end

jps@GRASSKEET ~/dev/elix
$ iex
Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> c("Cater.ex")
Cater.ex:1: warning: redefining module Cater
Cater.ex:3: warning: this expression will fail with ArithmeticError
[Cater]
iex(2)> Cater.cut(10)
** (FunctionClauseError) no function clause matching in Cater.cut/1
    Cater.ex:2: Cater.cut(10)
iex(2)>

【问题讨论】:

  • 哎呀!我真是个白痴。当我发布这个时,我有一种“感觉”,回去编辑,“果然”,elixir 不喜欢我的变量名大写的事实。一旦我将所有 N 更改为 n,它就会正确编译并运行。很抱歉打扰大家
  • 发生在我们最好的人身上:)
  • 也许您可以更改标题,以便人们可以轻松检索您的帖子:我在尝试 elixir 时也遇到了问题,所有内容都提醒 erlang,但一切都不一样 :o)
  • 所以,如果我更加关注 elixir-lang.org 网站上名为“Erlang/Elixir Syntax: A Crash Course”的部分,我会看到一个突出显示的部分这个错误。不过,总的来说,我发现到目前为止我看到的 Elixir 错误消息并不是很具有描述性。消息让我想起了我曾经在 Fortran 编译器中看到的一些神秘错误。我猜是“早期”。

标签: erlang elixir variable-names


【解决方案1】:

只是为了详细说明问题以及您收到错误的原因:

大写的标识符被视为原子的别名。例如:

iex(1)> N == :Elixir.N
true

所以当你有以下代码时:

iex(1)> defmodule Test do
...(1)> def foo, do: IO.puts "testing"
...(1)> end
iex(2)> Test.foo
testing

说的也一样

iex(3)> :Elixir.Test.foo
testing

由于大写标识符被视为符号,因此您基本上编写了以下程序:

defmodule Cater do
  def cut(0), do: 1
  def cut(:Elixir.N) when :Elixir.N>0, do: :Elixir.N + cut(:Elixir.N-1)
end

这是有效的,因为您可以对参数列表中的原子进行模式匹配,并且:Elixir.N > 0 是一个有效的表达式。

iex(1)> N > 0
true

考虑以下 Elixir 程序和输出:

iex(1)> defmodule Cater do
...(1)> def cut(0), do: IO.puts "cut(0)"
...(1)> def cut(N) when N > 0, do: IO.puts "cut(N)"
...(1)> end
iex(2)> Cater.cut(0)
cut(0)
iex(3)> Cater.cut(N)
cut(N)
iex(4)> Cater.cut(:Elixir.N)
cut(N)
iex(5)> Cater.cut(1)
** (FunctionClauseError) no function clause matching in Cater.cut/1
    iex:2: Cater.cut(1)

所以,您收到看似奇怪的错误消息 no function clause matching in Cater.cut/1 的原因是,您的程序在技术上没有任何问题(除了 cut(N) 的实际函数体——它会引发 ArithmeticError,Elixir 会警告您大约在编译时);这是完全有效的,它只是没有做你想让它做/你认为它做的事情。

【讨论】:

  • 值得指出的是,从 Elixir 到 Erlang 也会发生完全相同的问题。如果您在 Erlang 中使用 Elixir 的小写变量,它们将是原子,您将遇到完全相同的错误。 :D
  • 这太棒了!它真的帮助我理解这两种语言。
  • 好吧,我认为这个问题对于解释一种新的令人兴奋的语言中的语义与句法差异非常有帮助;尤其是从初学者的 4 行程序的角度来看,这似乎是正确的。我喜欢 Jose 的说明,在“反向”中也是如此。我感谢任何人的想法,将其改写为更清晰——也许是“顺便说一句,变量声明中的语义差异”。长生不老药和二郎? TIA,日本人
  • 嗯; Elixir/Erlang 中的“原子与变量”怎么样,或者 Elixir/erlang 上的“arth 错误”-> BTW,BinaryMuse 的解释对于理解为什么帕斯卡和我最初都犯了同样的错误非常有帮助。找到一种将其添加到 S/O 的方法将有助于为那些“难倒”的专业程序员提供快速的解决方案/解释。 [顺便说一句,进行反向编辑[erlang程序的所有n到N],从erlc产生了类似的'第4行的算术错误')。谢谢。
猜你喜欢
  • 2019-08-06
  • 2019-06-15
  • 2021-01-22
  • 2020-01-01
  • 2015-03-20
  • 2017-11-30
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多