2010-05-04 8 views
6

Donc j'ai utilisé Erlang pendant les huit dernières heures, et j'ai passé deux de ceux qui se cognent la tête contre le clavier en essayant de comprendre l'erreur d'exception que ma console continue de renvoyer. J'écris un programme de dés pour apprendre erlang. Je veux qu'il puisse appeler de la console à travers l'interpréteur erlang. Le programme accepte un certain nombre de dés, et est censé générer une liste de valeurs. Chaque valeur est supposée être entre un et six.Erreur d'exception dans Erlang

Je ne vais pas vous ennuyer avec les douzaines de micro-changements individuels que j'ai faits pour essayer de résoudre le problème (ingénierie aléatoire) mais je vais poster mon code et l'erreur.

La Source:

-module(dice2). 
-export([d6/1]). 

d6(1) -> 
    random:uniform(6); 
d6(Numdice) -> 
    Result = [], 
    d6(Numdice, [Result]). 

d6(0, [Finalresult]) -> 
    {ok, [Finalresult]}; 

d6(Numdice, [Result]) -> 
    d6(Numdice - 1, [random:uniform(6) | Result]). 

Quand je lance le programme de ma console comme si ... dice2:d6(1).

... Je reçois un nombre aléatoire entre un et six comme prévu . Cependant quand je lance la même fonction avec un nombre supérieur à un comme un argument que je reçois l'exception suivante ...

**exception error: no function clause matching dice2:d6(1, [4|3])

... Je sais II n'ont pas une fonction avec des arguments correspondant mais je ne Je ne sais pas comment écrire une fonction avec des arguments variables, et une variable numéro d'arguments.

J'ai essayé de modifier la fonction en question comme si ....

d6(Numdice, [Result]) -> 
    Newresult = [random:uniform(6) | Result], 
    d6(Numdice - 1, Newresult). 

... mais je me suis essentiellement la même erreur. Quelqu'un sait ce qui se passe ici?

Répondre

6

Il s'agit essentiellement d'une erreur de type. Lorsque Result est une liste, [Result] est une liste avec un élément. Par exemple, si votre fonction fonctionnait, elle retournerait toujours une liste avec un élément: Finalresult.

C'est ce qui se passe (en utilisant ==> pour « réduit à »):

d6(2) ==> %% Result == [] 
d6(2, [[]]) ==> %% Result == [], let's say random:uniform(6) gives us 3 
d6(1, [3]) ==> %% Result == 3, let's say random:uniform(6) gives us 4 
d6(0, [4|3]) ==> %% fails, since [Result] can only match one-element lists 

On peut supposer que vous ne voulez pas [[]] dans le premier appel, et vous ne voulez pas être Result 3 dans la troisième appel. Donc, cela devrait fixer:

d6(Numdice) -> Result = [], d6(Numdice, Result). %% or just d6(Numdice, []). 

d6(0, Finalresult) -> {ok, Finalresult}; 
d6(Numdice, Result) -> d6(Numdice - 1, [random:uniform(6) | Result]). 

Leçon: si une langue est typé dynamiquement, cela ne signifie pas que vous pouvez éviter d'avoir les bons types. Au contraire, cela signifie que le compilateur ne vous aidera pas à le faire autant qu'il le pourrait.

+1

Votre solution a fonctionné magnifiquement et m'a aidé à comprendre mon erreur. Je suis nouveau au paradigme fonctionnel donc il y a beaucoup à absorber. Où j'étais confus était de penser en appelant d6 (Numdice, résultat) avec une liste vide, tous les nouveaux appels finiraient par être seulement en mesure de faire correspondre à une liste vide comme l'un des paramètres de d6 parce que vous ne pouvez pas relier variables dans la portée. Je suppose que j'ai oublié que les règles de liaison ne s'appliquent qu'à une fonction donnée * avant * l'appel suivant [roule les yeux]. J'ai été pris dans le problème de correspondance, et j'ai oublié la longueur de l'élément. En tout cas, merci d'avoir répondu à ma question. – Jim

+0

N'oubliez pas que vous pouvez voter la réponse aussi bien que l'accepter :) –

+1

juste pour complétude: 'd6 (1)' vous donne un nombre, mais par ex. 'd6 (2)' vous donne '{ok, [Value1, Value2]}' qui pourrait conduire à d'autres bogues. – ZeissS