2010-05-04 11 views
6

Así que he estado usando Erlang durante las últimas ocho horas, y he pasado dos de esos golpeando mi cabeza contra el teclado tratando de descubrir el error de excepción que mi consola sigue repitiendo.Error de excepción en Erlang

Estoy escribiendo un programa de dados para aprender erlang. Quiero que pueda llamar desde la consola a través del intérprete de Erlang. El programa acepta una cantidad de dados, y se supone que genera una lista de valores. Se supone que cada valor está entre uno y seis.

No te aburriré con las docenas de microcambios individuales que realicé para intentar solucionar el problema (ingeniería aleatoria) pero publicaré mi código y el error.

La Fuente:

-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]). 

Cuando ejecuto el programa desde mi consola como tal ... dice2:d6(1).

... me sale un número aleatorio entre uno y seis, como se esperaba . Sin embargo cuando corro la misma función con cualquier número superior a uno como un argumento consigo la siguiente excepción ...

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

... sé II no tienen una función con argumentos a juego, pero me Don 's no sabe cómo escribir una función con argumentos variables, y una variable número de argumentos.

He intentado modificar la función de que se trate como tal ....

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

... pero tiene esencialmente el mismo error. Alguien sabe lo que está pasando aquí?

Respuesta

6

Esto es básicamente un error de tipo. Cuando Result es una lista, [Result] es una lista con un elemento. Por ejemplo, si su función funcionó, siempre devolverá una lista con un elemento: Finalresult.

Esto es lo que sucede (usando ==> para "reduce a"):

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 

Es de suponer que no desea [[]] en la primera convocatoria, y que no quieren ser Result 3 en el tercera llamada. Por lo que este debe solucionarlo:

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]). 

lección: si una lengua se escribe dinámicamente, esto no quiere decir que usted puede evitar que los tipos correctos. Por el contrario, significa que el compilador no te ayudará a hacer esto tanto como podría.

+1

Su solución funcionó maravillosamente y me ayudó a comprender mi error. Soy nuevo en el paradigma funcional, así que hay mucho que absorber. Donde estaba confundido estaba pensando en llamar a d6 (Numdice, Resultado) con una lista vacía, cualquier llamada nueva terminaría siendo capaz de coincidir con una lista vacía como uno de los parámetros de d6 porque no puede volver a enlazar variables en el alcance Supongo que olvidé que las reglas obligatorias solo se aplican dentro de una función determinada * antes * de la próxima llamada [gira los ojos]. Me quedé atrapado en el problema de coincidencia y me olvidé de la longitud del elemento. De todos modos, gracias por responder mi pregunta. – Jim

+0

No olvides que puedes votar la respuesta y aceptarla :) –

+1

solo por completness: 'd6 (1)' te da un número, pero p. 'd6 (2)' te da '{ok, [Value1, Value2]}' que podría conducir a otros errores. – ZeissS

Cuestiones relacionadas