2015-06-12 10 views
6

** Quindi, ho lavorato con Erlang, prima, e sono piuttosto tranquillo con esso. Sto solo cercando di imparare l'elisir.Perché ricevo un FunctionClauseError ("nessuna clausola della funzione corrispondente") in questo programma Elixir, tradotto da Erlang?

Recentemente stavo cercando di tradurre un esempio di 'lazy catering' in elisir e sono confuso sul motivo per cui non viene compilato, o viene compilato con un avviso e non funziona. Cosa mi manca, qui; Qualche idea? Il codice Erlang e 'run' sono le seguenti: **

[email protected] ~/dev/erlang 
$ cat cater.erl 

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

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

Quando scrivo Cater.ex in questo modo, si ottiene un errore che non ha senso per me:

[email protected] ~/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 

[email protected] ~/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)> 
+3

Arrrrgh! Che idiota sono. Non appena ho postato questo messaggio, ho avuto un 'sentimento', sono tornato indietro ed editato, e 'abbastanza sicuro', l'elisir non mi piaceva il fatto che i miei nomi variabili fossero maiuscoli. Una volta che ho cambiato tutti gli Ns in n, è stato compilato e eseguito correttamente. Mi dispiace disturbare il tuo – jpsthecelt

+1

Succede al meglio di noi :) – jjbohn

+2

Forse potresti cambiare il titolo, così le persone possono recuperare facilmente il tuo post: ho avuto anche questo problema nel provare elisir, dove tutto ricorda erlang, ma tutto è diverso: o) – Pascal

risposta

7

Solo per espandere il problema e perché hai ricevuto l'errore che hai fatto:

Gli identificativi in ​​maiuscolo vengono considerati come alias per gli atomi. Per esempio:

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

Quindi, quando si ha il seguente codice:

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

E 'lo stesso che dire

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

Dal identificatori maiuscole sono trattate come simboli, hai scritto in sostanza il seguente programma:

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

Questo è valido, poiché è possibile eseguire la corrispondenza del modello sugli atomi nell'elenco degli argomenti e :Elixir.N > 0 è un'espressione valida.

iex(1)> N > 0 
true 

Si consideri il seguente programma di Elixir e l'uscita:

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) 

Quindi, il motivo che hai il messaggio di errore apparentemente strano no function clause matching in Cater.cut/1 è che non c'è tecnicamente niente di sbagliato con il vostro programma (ad eccezione del corpo della funzione reale di cut(N) -it potrebbe aumentare un ArithmeticError, di cui Elixir ti avvisa in fase di compilazione); è perfettamente valido, semplicemente non fa quello che volevi che facesse/quello che pensavi che facesse.

+10

Vale anche la pena sottolineare che lo stesso identico problema sarebbe accaduto passando da Elixir a Erlang. Se si usano le variabili minuscole di Elisir in Erlang, saranno atomi e si avrà esattamente lo stesso errore. : D –

+0

Questo è fantastico! Mi aiuta davvero a capire le due lingue. – jpsthecelt

+0

Bene, vedo questa domanda come molto utile per spiegare le differenze semantiche contro sintattiche all'interno di un nuovo ed eccitante linguaggio; soprattutto dal punto di vista del programma a 4 linee del principiante che apparentemente era corretto. Mi piace la nota di Jose che lo stesso è vero nella "direzione inversa". Apprezzo le idee di chiunque a riformularlo per essere più chiaro, forse "le differenze semantiche nelle dichiarazioni variabili". Elisir ed Erlang '? TIA, jps – jpsthecelt