Newsgroup: it.comp.os.linux.development
Titolo: Come scrivere due funzioni che si richiamano a vicenda in OCAML?

Non so se questo sia il gruppo giusto per questa discussione, ma ho
visto alcuni post in cui si parla di OCAML. Ho un problema con un
programmino.
// questa funzione mi dice il contenuto della stanza n
let rec contenuto n lst = match lst with
(x,y)::rest -> if (x==n) then y
	      else contenuto n rest;;
// il labirinto è visto come un grafo, start è il nodo di partenza e
shoot un booleano, se vale true posso sparare, se vale false ho finito
i colpi
let labirinto graph start shoot = match graph with
[] -> fail
|n::rest -> n::guarda(succ graph n shoot);;
// la funzione guarda decide tra le varie stanze in cui posso andare
qual'è o quali sono quelle in cui posso andare e poi tramite
backtracking trova la soluzione al labirinto.
let rec guarda lst shoot = match lst with
[] -> raise Fail
|x::xs -> if (contenuto x contents == Monster && shoot == true)
	then try labirinto graph x true with Fail -> guarda xs true
	else if (contenuto x contents == Monster && shoot == false)
	then guarda xs false
	else if (contenuto x contents == Gold)
	then raise Success
	else if (contenuto x contents == Vuota)
	then try labirinto graph x true with Fail -> guarda xs true;;
Quando compilo questo è il risultato:
#           type oggetto = Gold | Monster | Vuota
type contents = (int * oggetto) list
type 'a graph = ('a * 'a) list
val contents : (int * oggetto) list =
  [(1, Vuota); (2, Vuota); (3, Vuota); (4, Monster); (5, Monster);
   (6, Monster); (7, Vuota); (8, Gold)]
#   exception Success
#   exception Fail
#             ..........................match lst with
  (x,y)::rest -> if (x==n) then y
  	      else contenuto n rest..
val contenuto : 'a -> ('a * 'b) list -> 'b = <fun>
#           Characters 93-97:
  |n::rest -> n::guarda(succ graph n shoot);;
                        ^^^^
This function is applied to too many arguments
#                         Characters 136-145:
  	then try labirinto graph x true with Fail -> guarda xs true
            ^^^^^^^^^
Unbound value labirinto
#

 
[ BIG CUT ]
In Ocaml, le funzioni mutuamente ricorsive vanno dichiarate con la sintassi
let rec ping () = pong ()
and pong () = ping ()
Il primo *rec* dice che la funzione può contenere richiami a se stessa 
(ricorsività)
l'*and* permette al compilatore di esecuire una dichiarazione in 
contemporanea. In questo caso *and* estende anche la clausola rec, 
quindi è come dichiarare contemporaneamente due (o più) funzioni che si 
possono richiamare mutuamente.
E' importante dire che l'uso di *and* senza *rec* permette di fare molte 
altre cose, un esempio classico è uno scambio di valori
let a = b and b = a
come si vede da questo esempio
Objective Caml version 3.08.2
# let a=1;;
val a : int = 1
# let b=2;;
val b : int = 2
# let a=b and b=a;;
val a : int = 2
val b : int = 1
#
Esistono, per l'Ocaml, delle mailing list (per principianti ed esperti) 
in inglese e francese alle quali ci si può iscrivere sul sito dell'inria
http://caml.inria.fr
Tutte le cose che ho scritto, poi, sono anche disponibili sul manuale 
dell'Ocaml (sempre scaricabile o consultabile online all'url
http://caml.inria.fr/pub/docs/manual-ocaml/index.html
o come sidebar di Mozilla/firefox all'url
http://caml.inria.fr/resources/mozilla-sidebar.en.html
Luca