Frage

Ich wollte eine Schwanz-rekursive Version von List.map haben, also schrieb ich meine eigenen. Hier ist sie:

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

Jedes Mal, wenn ich diese Funktion zu kompilieren, erhalte ich:

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

Die Tutorial sagt, dass dies bedeutet, dass ich versuche, eine Funktion ohne nicht zu schaffen -optional Argumente. Aber die Funktion oben klar nimmt nicht optionale Argumente.

Ich bin wahrscheinlich nur tun, etwas wirklich dumm, aber was?

War es hilfreich?

Lösung

Die bisherigen Lösungen kompilieren, aber das erwartete Ergebnis nicht geben. Die Funktion f wird nie auf die Argumente angewendet. Ein richtiger Code lautet:

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

Der abgeleitete Typ ist:

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

... im Gegensatz zu dem falschen:

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

Bitte beachten Sie, dass der Ergebnisliste umgekehrt wird:

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

... und entspricht der Funktion rev_list aus die Liste Modul :

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

Sie wollen also können Sie Ihre Funktion in sich ändern:

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

... was auch Schwanz rekursiv sein sollte (laut Handbuch) und gibt die Liste in der ursprünglichen Reihenfolge:

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

Andere Tipps

Ja Ihr nicht optionales Argument kann nicht zuletzt, weil da OCaml Teil Anwendungen unterstützt, eine Funktion, um ein letztes optionales Argument fehlt wie eine aussehen wird teilweise angewandte Funktion, die für das optionale Argument noch sucht. Der einzige Weg, es zu sagen, dass Sie nicht beabsichtigen, das optionale Argument zu schaffen, besteht darin, dass sie sieht, dass Sie ein Argument, nachdem sie zur Verfügung gestellt haben.

Wenn Sie es zuletzt haben, können Sie ein Dummy unit Argument, nachdem er gesagt:

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

Aber in diesem Fall ja die Reihenfolge zu ändern wäre besser.

Sie benötigen ein nicht-optionales Argument nach die optional ein. Ändern Sie einfach die Reihenfolge der Argumente Ihrer Funktion:

let rec list_map f ?(accum=[]) l=
  match l with
    head :: tail -> list_map f  ~accum:(head :: accum) tail
  | [] -> accum;;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top