il problema è che a ogni chiamata stai cercando di aggiungere una lista ad una lista...
La soluzione è creare la lista al contrario e poi invertirla
codice:
let rec crea (n,l1,g1) = match g1 with
[] -> List.rev l1
| x::xs -> match x with (a,b,c,d) -> if a=n then crea(n,b::l1,xs)
else crea(n,l1,xs);;
Alternativamente puoi concatenare le due liste ad ogni passo, ma è (quasi) sicuramente meno efficiente
codice:
let rec crea (n,l1,g1) = match g1 with
[] -> l1
| x::xs -> match x with (a,b,c,d) -> if a=n then crea(n,l1@[b],xs)
else crea(n,l1,xs);;
Puoi anche utilizzare il seguente meccanismo, ma è a rischio di stack overflow
codice:
let rec crea (n,g1) = match g1 with
[] -> []
| x::xs -> match x with (a,b,c,d) -> if a=n then b::crea(n,xs)
else crea(n,xs);;
Puoi infine utilizzare la libreria standard (che però è a rischio di stack overflow)
codice:
let crea (n,g1) = List.map (fun (a,b,c,d) -> b) (List.filter (fun (a,b,c,d) -> a=n) g1)
Per risolvere il rischio di stack overflow potresti fare
codice:
let crea (n,g1) = List.rev (List.rev_map (fun (a,b,c,d) -> b) (List.filter (fun (a,b,c,d) -> a=n) g1))
Infine tieni conto che se la tua lista è breve non avrai alcun problema di stack overflow.
Ah, una nota! ad ogni chiamata della funzione ricorsiva crei e distruggi una tupla, potresti evitarlo. Inoltre le curried functions sono più conformi allo stile di ocaml e più comode da usare!