2009-11-03 7 views
8

Je voulais avoir une version récursive en queue de List.map, j'ai donc écrit la mienne. Ici, il est:L'argument facultatif ne peut pas être effacé?

let rec list_map f l ?(accum=[])= 
    match l with 
     head :: tail -> list_map f tail ~accum:(head :: accum) 
    | [] -> accum;; 

Chaque fois que je compile cette fonction, je reçois:

File "main.ml", line 69, characters 29-31: 
Warning X: this optional argument cannot be erased. 

Le tutorial dit que cela signifie que je suis en train de créer une fonction sans argument non en option. Mais la fonction ci-dessus prend clairement des arguments non optionnels.

Je suis probablement en train de faire quelque chose de vraiment idiot, mais quoi?

+1

vous devriez jeter un coup d'oeil aux messages récents sur la liste de diffusion d'ocaml au sujet des cartes récursives de queue. http://groups.google.com/group/fa.caml/browse_thread/thread/8b2a70a767e6a433 – nlucaroni

Répondre

3

Les solutions précédentes se compilent mais ne donnent pas le résultat attendu. La fonction f n'est jamais appliquée aux arguments. Un code est correct:

let rec list_map f ?(accum = []) l = match l with 
    | head :: tail -> list_map f ~accum:(f head :: accum) tail 
    | [] -> accum;; 

Le type inféré est:

val list_map : ('a -> 'b) -> ?accum:'b list -> 'a list -> 'b list = <fun> 

... contrairement à la mauvaise:

val list_map : 'a -> ?accum:'b list -> 'b list -> 'b list = <fun> 

S'il vous plaît noter que le résultat la liste est inversée:

# list_map ((**) 2.) [1.;2.;3.;4.];; 
- : float list = [16.; 8.; 4.; 2.] 

... et est égal à la fonction rev_list from the List module:

# List.rev_map ((**) 2.) [1.;2.;3.;4.];; 
- : float list = [16.; 8.; 4.; 2.] 

Vous voudrez peut-être changer votre fonction dans:

let rec list_map f ?(accum = []) l = match l with 
    | head :: tail -> list_map f ~accum:(f head :: accum) tail 
    | [] -> List.rev accum;; 

... qui devrait être récursive et (selon le manuel) et renvoie la liste dans l'ordre original:

# list_map ((**) 2.) [1.;2.;3.;4.];; 
- : float list = [2.; 4.; 8.; 16.] 
12

Vous avez besoin d'un argument non-optionnel après l'option. changer juste l'ordre des arguments de votre fonction:

let rec list_map f ?(accum=[]) l= 
    match l with 
    head :: tail -> list_map f ~accum:(head :: accum) tail 
    | [] -> accum;; 
+1

Merci beaucoup.Ça va me trébucher beaucoup. Je suis habitué à faire des arguments optionnels comme Python et C++. :-( –

13

Ouais votre argument non-option ne peut pas être le dernier, car depuis OCaml prend en charge les applications partielles, une fonction manquante un dernier argument optionnel va simplement ressembler à un Fonction partiellement appliquée qui cherche toujours l'argument optionnel. La seule façon pour lui de dire que vous n'avez pas l'intention de fournir l'argument optionnel est qu'il voit que vous avez fourni un argument après lui.

Si vous devez avoir la dernière, vous pouvez mettre un argument unit factice après:

let rec list_map f l ?(accum=[])() = 
    match l with 
     head :: tail -> list_map f tail ~accum:(head :: accum)() 
    | [] -> accum;; 

Mais dans ce cas, oui, changer l'ordre serait mieux.

+0

Donc, l'application de la fonction nécessite également l'argument factice '()'. – weakish

Questions connexes