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付け忘れて罵倒されました!