OCamlで「与えられた木から、子→親への対応を作る」

与えられた木から、子→親への対応を作る

本能のままにOCamlで書いてみたら次のようになりました。

type tree = string * tree list;;

let tree : tree =
  ("Root",
    ["Spine",
      ["Neck", ["Head", []];
       "RClavicle", ["RUpperArm", ["RLowerArm", ["RHand", []]]];
       "LClavicle", ["LUpperArm", ["LLowerArm", ["LHand", []]]]];
     "RHip", ["RUpperLeg", ["RLowerLeg", ["RFoot",[]]]];
     "LHip", ["LUpperLeg", ["LLowerLeg", ["LFoot",[]]]]; ])
;;

let rec foo res = function
  | name, []   -> res
  | name, list ->
    let res' = (List.map (fun (name', _) -> name', name) list) @ res in
    List.fold_left foo res' list
;;

List.iter (fun (c, p) -> Printf.printf "%s, %s\n" c p) (foo [] tree);;

別に面白いところはありませんが(というかもっとスマートに書けそうですよね)、tupleで木をつくってみました。んでもって、-rectypes オプションを付け忘れて、罵倒されました。泣きたい気持ちです。

追記

jijixi’s diary - 与えられた木から、子→親への対応を作る

わー、sexplib版だ。最初sexplibを使おうと思ったのですが、今の環境に入れてない事を思い出して、godiでとりあえずインストールして満足。やっぱり面倒だから!と思い直したんですよね。

あとまあ、せっかく「順序は問わない」って言われてるんだからリストを繋ぐときは rev_append を使おうよ :-) とか。

え、だってマニュアルには"10000要素以下のlistだったらtail-recursiveでなくても全然OKだから!"みたいな事書いてあるから、今の今までそういうものだと信じ切ってました。ひょっとして実際には皆普段から List.rev_append を使っているものなのでしょうか。"@"が好きだから、ちょっとショック。

と思って手元のアレコレを見直してみたら、自分はList.rev_appendを使うクセが全然ついてないので問題があると思いました。普段からList.rev_appendを使うことにしようと思います。ご指摘に感謝致します。

さらに追記

id:kmizushima さんからご指摘頂きましたように"| name, [] -> res"の部分が全くの無駄でした。本気で気付かなかった、なんてこった!というわけで以下のようになるわけですね。ありがとうございました。

type tree = string * tree list;;

let tree : tree =
  ("Root",
    ["Spine",
      ["Neck", ["Head", []];
       "RClavicle", ["RUpperArm", ["RLowerArm", ["RHand", []]]];
       "LClavicle", ["LUpperArm", ["LLowerArm", ["LHand", []]]]];
     "RHip", ["RUpperLeg", ["RLowerLeg", ["RFoot",[]]]];
     "LHip", ["LUpperLeg", ["LLowerLeg", ["LFoot",[]]]]; ])
;;

let rec foo res (name, list) =
  let res' = (List.map (fun (name', _) -> name', name) list) @ res in
  List.fold_left foo res' list
;;

List.iter (fun (c, p) -> Printf.printf "%s, %s\n" c p) (foo [] tree);;

んでもってまたまた-rectypes付け忘れて罵倒されました!