å®åã§ä½¿ãOCaml - æ³¥èãä»äºããµã¯ã£ã¨ããªãæ¹æ³
ããã°ã©ããå®åã§åºä¼ãã®ã¯ãåé¡ãæ´çããããã¬ã¤ãªä»äºã°ãããããªãããããã¯ãã«æ¬è³ªçãããªãé¨åã§ãããã°ã©ã ãæ¸ãå¿ è¦ã«è¿«ããããããããéçºæ¹æ³è«ã§ã¯æ½è±¡åããã¦ãã¾ããä»ããã«ããã½ããã¦ã§ã¢éçºè ã®æ©ã¿ã ã
ä»æ¥ã¯ãç§ãä»äºã§æ¸ããOCamlã®ã³ã¼ããæãã¦ãå¦ä½ã«OCamlãããã°ã©ãã®ä»äºã®éå ·ã¨ãã¦åªãã¦ãããã主張ããããæ³¥èããé¢æ°çã§ãªããã¨ã¬ã¬ã³ããã®ãããããªããçæ´»èã®ããã³ã¼ãã ãå¤åå ã¯OCamlãã¡ã¤ã³è¨èªã¨ãã¦ä½¿ã£ã¦ãããç 究æã¨ãã§ã¯ãªãæ®éã«åè¨éçºãçæ¥ã¨ãã¦ããä¼ç¤¾ã ãOCamlã¯çè«ä¸è¾ºåã§ãããã¢åãã§ãç¾å®ã®ã½ããã¦ã§ã¢éçºã«ã¯ä½¿ããªããã¨ãã誤解ãä¸ãä¸ãããããããªãããå ¨ããããªãã¨ã¯ãªãã (Haskellãããã ãã©ãããã¯ã¾ãã®æ©ä¼ã«)
ããã«OCamlãåªãã¦ãããã«ã¤ãã¦ã®æ¦è«ããã話ã¯ãOCamlãæ°å人ä½å¶ã§10年使ã£ã¦ããJane Street Capitalã® Yaron Minskyã«ãã ãªã次ã«å¦ã¶è¨èªã¯é¢æ°åã§ããã¹ãã ãããã¡èªã¿ããã°ããã¨æããç¹ã«ããªãOCamlãªã®ã?ãã®ããããããã¯ACM Queueã¨ããç«æ´¾ãªéèªã®è¨äºã ãããã¡ããçèªããã«è¶ãããã¨ã¯ãªãã¨æãã
追è¨ï¼ãã£ããæ§ (@camloeba)ã«ã³ã¼ããæ¹åãã¦ããã ãã¾ãã! âã®ã³ã¼ãã¯ã¶ãã¯ãªããã¦ã¤ãã¤ãã§ããããé¢ç½ãæ¹è©ä»ãã§èªã¿æããªã£ã¦ãã¾ãã
ç¶æ³: éèæ¥ã®ã¡ãã»ã¼ã¸éä¿¡ãããã³ã« on TCP/IP
ä»åã®ã³ã¼ããæ¸ãã«è³ã£ãç¶æ³ã«ã¤ãã¦æ¸ãã¾ãã
æå®ããéæã®æ ªä¾¡ãæç³»åã§åå¾ããã½ããã¦ã§ã¢ãæ¸ããä»äºã ã£ã(*ã¡ãã£ã¨ã¼ããã¦ãã*)ãããã§åé¡ã«ãªã£ãã®ã¯ãéä¿¡å¦çã®å®è£
ã ã
ãããã³ã«ã¯ä¸æµå´ã«ããå®ç¾©ãããTCP/IPä¸ã«ä½ãããç¬èªã®ãã®ãç¹ãã£ã±ãªãã®ã¹ããªã¼ã ã«ãã¡ãã»ã¼ã¸ã¨å¼ã°ããåä½ã®ããã¾ãããããã¤ãé£çªãæ¯ããã¦æµãã¦ããããã«ãªã£ã¦ããããã®åºæ¬ãããã³ã«ã®ä¸ã§ãæ ªä¾¡ã®éæã³ã¼ãã¨ãããæ¥ä»ç¯å²ãæå®ãã¦ãªã¯ã¨ã¹ãããã¨ãã¬ã¹ãã³ã¹ã¨ãã¦æ ªä¾¡ã®ç³»åãè¤æ°ã®ã¡ãã»ã¼ã¸ã«è¼ã£ã¦è¿éããã¦ããããã¾ãã¤ã³ã¿ã¼ãããæ代ãæãããããããã³ã«ã§ã¯ãªãããã©ãããããªã¢ã«ãªéèæ¥çã®éä¿¡ãããã³ã«ã®ã²ã¨ã¤ãªã®ã ã
説æã®ãããA社ã®1æ¥ãã4æ¥ã¾ã§ã®æ ªä¾¡ãåå¾ãããªã¯ã¨ã¹ãã
è¦æ±ï¼ ("A",1,4)
ã¨æ¸ããã¬ã¹ãã³ã¹(ã¡ãã»ã¼ã¸ã®å)ã¯
å¿çï¼[1100; 1098; 1081; 1120]
ã®ããã«æ¸ãããã«ããã
æ³¥èãåé¡
調ã¹ã¦ãããã¡ã«ããããã³ã«ã®ã¢ããªå±¤ã§æ¬²ããæ©è½ãæ¬ ãã¦ãããã¨ãããã£ãã ã¨ããã®ã¯ãã¬ã¹ãã³ã¹ã¨ãªã¯ã¨ã¹ãã対å¿ã¥ããIDããªãã£ãã®ã ã
ããã¯å¤§ããªåé¡ã ã£ããåãåã£ãã¡ãã»ã¼ã¸ãã©ã®ãªã¯ã¨ã¹ãã«å¯¾å¿ããã¬ã¹ãã³ã¹ã®ãã®ããããã«ã¯ããããªãã®ã ã è¤æ°ã®ãªã¯ã¨ã¹ããåæã«æããã¨ãè¤æ°ã®ã¬ã¹ãã³ã¹ã®ç³»åãã¹ããªã¼ã ä¸ã§ã¤ã³ã¿ã¼ãªã¼ã(æ··ãããªãã)ããªããè¿éããã¦ãã¾ãã
è¦æ±ã®åï¼[("A",1,4); ("B",2,3)]
å¿çã®åï¼[1100; 1098; 910; 1081; 940; 1120] (* 1100, 1098, 1081, 1120 㯠A社ã®æ ªä¾¡, 910, 940 㯠B社ã®æ ªä¾¡ *)
ãªãã¨ãããã¨ã â¦
幸ããã¬ã¹ãã³ã¹ã®ãããã«ã¯ãªã¯ã¨ã¹ããããéæã³ã¼ãã¨æ¥ä»ç¯å²ãå
¥ã£ã¦ããã
å
·ä½çã«ã¯ãä¸ã®å¿çã®åã¯ãããããå«ããã¨ã次ã®ãããªæãã«ãªãã (ããã§a=("A",1,4), b=("B",2,3)ã¨ç¥è¨ãã¾ã)
å¿çã®åï¼[(a,1100); (a,1098); (b,910); (a,1081); (b,940); (a,1120)]
ããããä¾ç¶ã¨ãã¦ãåããªã¯ã¨ã¹ãã2åæããå ´åã«ã¯ãã¼ããã¶ã£ã¦ãã¾ãã
ãããªããã°ã©ã ãæ¸ãã¾ãã
次㮠OCaml ã®é¢æ° receive_quote ã¯ãéæã®æ¼éã«ä¸æ¯ã§æ¸ããã³ã¼ãã ãã©ããããªãã«ã¾ã¨ãã«åãã¦ããã
ãã¤ã³ãã¯ã
- ã³ã¼ããæ¯è¼ççãã
- ãããã¡ãããè¤éãªæ§é ããã¦ããã«ãé¢ããããå®è¡æã¨ã©ã¼ã«ãªããããªãããããããã¦ããªã
- å¼æ°ã®åãã»ã¨ãã©æ¸ãã¦ããªã (å®éãç¡ãã¦ããã)
ãã£ããæ¸ããã ãã®ã³ã¼ãã ããRubyãPythonãªãããããã¡ãã£ã¨ã ãå°ãªãåéã§æ¸ãããããããªããã©ãå®è¡æã¨ã©ã¼ã«æ©ã¾ããããã¨ã«ãªããããããªããç§ãªããã¶ããããªãããããOCamlãªããã³ã³ãã¤ã«æã«ã»ã¨ãã©ã®ã¨ã©ã¼ãæ¤åºãããããå®éãã³ã³ãã¤ã«æåå¾ã¯æå³éãåä½ãã¦ããã®ã§ãé±æ«ã¯ä»äºãå¿ãã¦éãã§æ®ãããã
ã³ã¼ãã«å ¥ãåã«ãã£ã¨è©³ç´°ãªãã¨ãæ¸ãã¨ãåã¡ãã»ã¼ã¸ã«ã¯ãé£çªãã¨ããªã¯ã¨ã¹ãå ¨ä½ã®ã¡ãã»ã¼ã¸æ°ããæ¯ããã¦ããã
å¿çã®åï¼[(a,1100,0,4); (a,1098,1,4); (b,910,0,2); (a,1081,2,4); (b,940,1,2); (a,1120,3,4)]
ã¨ãã£ãæãã ã
OCamlãããç¥ããªã人ã®ããã«ããããã³ã¡ã³ããæ¸ããããã©ãæ®æ®µã¯ãããªã«è©³ç´°ã«æ¸ãããããªããã³ã¡ã³ããå¤ãããã¼ã¸ã§ã³ã¯ http://ideone.com/aWBKX ã«ãããããï¼ çµæ§ãã©ãæ¸ãã¦ãããªâ¦
type request = string * string * string (* ãªã¯ã¨ã¹ã. éæid,æéfrom,æétoã®ä¸ã¤çµ *) ;; let code (c,_,_) = c type quote = { price:int; } (* éæã®å¤æ®µï¼å®éã«ã¯ãä»ã«ãå¤ãã®æ å ±ãå«ã¾ãã¦ãã *) ;; type response = { req: request; (* ã©ã®ãªã¯ã¨ã¹ãã«å¯¾ããã¬ã¹ãã³ã¹ã *) body: quote; (* ã¬ã¹ãã³ã¹ã®å 容 *) seq:int; (* ã¬ã¹ãã³ã¹ä¸ãä½çªç®ã®ã¡ãã»ã¼ã¸ã *) total:int; (* å¿çã¡ãã»ã¼ã¸ã®ç·æ° *) } ;; (* åä¿¡éä¸ã®ã¬ã¹ãã³ã¹ã®ãããã¡ã次ã®é£æ³ãã¼ãã«(Map)ã§æ§æããã OCamlã®Mapã¯ããã¼ã®åã¨æ¯è¼é¢æ°ãMap.Makeã«æ¸¡ãã°å¾ããã *) module M = Map.Make ( struct type t = request (* ãªã¯ã¨ã¹ãåããã¼ã¨ã㦠*) let compare = Pervasives.compare (* ä½ãé©å½ã«æ¯è¼ãã¦ããã *) end) ;; (* ã¬ã¹ãã³ã¹ãä¿æãããããã¡ã ä¸æ¯ã§æ¸ããã®ã§ãããè¤éãªåã ãã ãªã¯ã¨ã¹ãããã¼(ä¸è¨)ã¨ãã¦ãåä¿¡éä¸ã®ã¬ã¹ãã³ã¹ãã㢠(int * quote option array) ã§ä¿æããã ãã®ãã¢ã¯ (åä¿¡æ¸ã¿ã¡ãã»ã¼ã¸æ°, éæãã¼ã¿ã®é å) ã¨ããæå³ã ã - æªåä¿¡ã®ã¡ãã»ã¼ã¸ãNoneã§åãã¦ããããããã option åã®é åã«ãªã£ã¦ããã - åããã¼ããã¤è¤æ°ã®ã¬ã¹ãã³ã¹ãåæã«æ±ãæ ¼ç´ããããããªã¹ãã«ãã¦ããã - ã°ãã¼ãã«å¤æ°ãªã®ã¯éãããã©ãã¯ãã¼ã¸ã£ã«å ¥ããã°ããã«ãªãã¨ããªã *) let buf : (int * quote option array) list M.t ref = ref M.empty ;; (* æ ªä¾¡ã®ãªã¹ãããã¼ã¿ãã¼ã¹ã«ä¿åãã. ããã¼ *) let save (code:string) (quotes:quote option list) : unit = () ;; (* ã¡ãã»ã¼ã¸rããããã¡ã«æ ¼ç´ããã ã¬ã¹ãã³ã¹å ¨ä½ãå¾ãããããsaveã§ä¿åããã *) let receive_quote (r:response) : unit = if r.total=1 then save (code r.req) [Some r.body] (* ç·ã¬ã³ã¼ãã1件ã®ã¿ã§ããã°ããã«ä¿å *) else begin let map = !buf in (* ãã®ãªã¯ã¨ã¹ãã«å¯¾ããã¬ã¹ãã³ã¹ã®ãªã¹ã(æ´æ°å) *) let all = try M.find r.req map with Not_found -> [] in (* ãããã¡ã«æ°ããã¬ã¹ãã³ã¹ã追å *) let newentry () = let arr = Array.make r.total None in (* ã¬ã¹ãã³ã¹å ¨ä½ãNoneã§åæå *) arr.(r.seq) <- Some r.body; buf := M.add r.req ((1, arr)::all) map (* 1ã¤åä¿¡ãã¾ãããã¨ãããã¡ãæ´æ° *) in (* ã¬ã¹ãã³ã¹ã®ãªã¹ããèµ°æ»ãé©åãªä½ç½®ã«æ ¼ç´ / ã¬ã¹ãã³ã¹å ¨ä½ãæºãããããä¿å *) let rec addentry rest = function | [] -> newentry () (* åä¿¡ãã¿ã¬ã¹ãã³ã¹ãªã. æ°ããã¬ã¹ãã³ã¹ã追å ãã *) | (cnt, arr) as y::ys -> (* åä¿¡ãã¿ã¬ã¹ãã³ã¹ãã *) match arr.(r.seq) with (* å½è©²ã®é£çªã¯åä¿¡æ¸ã¿ã *) | None -> arr.(r.seq) <- Some r.body; (* ã¬ã¹ãã³ã¹ã®è©²å½ããé£çªãæºãã *) if cnt+1=r.total then begin (* ã¬ã¹ãã³ã¹å ¨ä½ãæºãããã. ä¿åå¾ããã®é åããããã¡ããé¤ã *) save (code r.req) (Array.to_list arr) (* ä¿å *); buf := M.add r.req (List.rev_append rest ys) map (* yã®åé¤ã«ãããããã¡ãæ´æ° *) end else (* ã¾ã足ããªãï¼åä¿¡æ¸ã¿æ°ãã¤ã³ã¯ãªã¡ã³ãããããã¡ãæ´æ° *) buf := M.add r.req (List.rev_append rest ((cnt+1, arr)::ys)) map | Some q -> (* ãã®ã¬ã¹ãã³ã¹ã§ã¯æ ¼ç´æ¸ã¿. 次ã®ã¬ã¹ãã³ã¹ãè¦ã *) addentry (y::rest) ys in addentry [] all end ;;
ç°¡åãªåä½ç¢ºèª
ããã°ã©ã å ¨ä½ã¯ http://ideone.com/6tUYa ã«ããã
次ã®ããã«å ¥åãä¸ãããã¨ãã§ããã Aã®ã2ã¤,Bã®ã1ã¤ãã¬ã¹ãã³ã¹ãæ¥ãç¶æ³ã ã
let _ = let a="A","1","4" and b = "B","1","2" in let resps = [ {req=a; body={price=1100}; total=4; seq=0}; {req=a; body={price=1098}; total=4; seq=1}; {req=a; body={price=1100}; total=4; seq=0}; {req=b; body={price=910}; total=2; seq=0}; {req=a; body={price=1098}; total=4; seq=1}; {req=a; body={price=1081}; total=4; seq=2}; {req=a; body={price=1081}; total=4; seq=2}; {req=a; body={price=1120}; total=4; seq=3}; {req=b; body={price=940}; total=2; seq=1}; {req=a; body={price=1120}; total=4; seq=3}; ] in List.iter receive_quote resps
saveé¢æ°ããç»é¢ã«ããªã³ãããããã«ãã¦ããã®ã§ã次ã®ãããªåºåãå¾ãããï¼
A 1100;1098;1081;1120; B 910;940; A 1100;1098;1081;1120;
çµè«
åãã³ã¼ããJavaã§æ¸ããã¨æã£ã¦ããããã©ãã¡ãã£ã¨å¤§å¤ããã§ãããªæ°ãèµ·ããªãã®ã§ããã¯èª°ãç©å¥½ãã«ä»»ãããã
åä¸å
«ä¹ãOCamlã®ã»ããJavaããä¿å®æ§ãé«ãè¦ãããã³ã¼ãã«ãªãã¯ãã§ãããã¯ä¸ã®ã³ã¼ãããã£ã¨ã¨ã³ã¿ã¼ãã©ã¤ãºçã«(log4jçãªãã®ã«ã«ãã°ãåºãã¨ããã¢ãµã¼ã·ã§ã³ãåãè¾¼ãã¨ããä¾å¤çç¶æ³ã«å¯¾å¦ããã³ã¼ããå
¥ããã¨ãã§)æ¸ãå ãã¦ãå¤ãããªãã ããã
ããã¾ã§æ¸ãã¦ããã¦ä½ã ããã©ãOCamlã§ãã¾ãããã°ã©ã ãæ¸ãæ¹æ³ã¨ãã¯ããããããªãã ãã ãä¸ã®å ´åã¯ã
- ãã¼ã¿æ§é ãå ã«æ±ºãããã¬ã¹ãã³ã¹ã®ãã¼ã§å¼ãããã«Mapãå¿ è¦ã ãªãã§ãã©ã³ãã ã¢ã¯ã»ã¹ãªã®ã§é åãããã«ããã¼ã被ãã®ã§ãªã¹ãã«ãã¦â¦ç ´å£çã«æ´æ°ããããããã¡ã ããrefã«ãã¨ãã風ã«ã
- ããã¦é¢æ°æ¬ä½ããä¸ã§æ±ºãããã¼ã¿æ§é ããªããããã«æ¸ããã
ã¨ããæé ã ã£ãããã«æãã ãã¤ã§ã使ããããã§ã¯ãªãããã©ãã¨ããããåã決ãã¦ããã¨ã¯ã¬ãªã¬ãªã³ã¼ããæ¸ãã¦ãåã¨ã©ã¼ãã¤ã¶ãã¦ããã°ããã¤ã®ã¾ã«ãåé¡ã¯è§£ãã¦ããã
OCamlã¯ãä½ãæ¦å¿µçã«é£ããããã§ã¯ãªããé¢æ°ããã°ã©ãã³ã°ã§å®è¡å¹çãé«ããããã®ã¡ãã£ã¨ããã¤ãã£ãªã ã¯ãããããããªã(ä¸ã®ã³ã¼ãã§ããrestã¨List.rev_appendã¨ã)ãã©ãåºæ¬çã«ã¯ã¹ãããªã¨ããç°¡æ½ãªè¨èªã ãããªãã¨ãã£ã¦ãå¤ç¸æ§ã¨å®å ¨ãªåæ¨è«ãå¬ããã
ã¾ãä¸ã®å¯ä½ç¨ããªããªã®ä¾ãè¦ãã°ãããããå®ã®ã¨ãããOCaml ã§é¢æ°åããã°ã©ãã³ã°ã«ãã ããå¿ è¦ã¯ãªãã®ã§ãããã¨ããããcaml.inria.fr/ocaml ã«ã¯é¢æ°åãªãã¦è¨èã¯ä¸ã¤ãã§ã¦ããªãã
Haskellã®ç´ç²é¢æ°çãªãã¬ã¼ãã¼ã¨ã¢ããã®è©±ã¯ç¥ç好å¥å¿ãããããããFRPã®ããã«æ ¹æ¬çãªè§£æ±ºçã¯å¤¢ãä¸ããããè¦ãç®ãã¨ã¬ã¬ã³ãã ãä¸æ¹ãOCamlã¯ããã¾ã§ãC++,Java,RubyãPythonã®ãããªæ¢åã®ããã°ã©ãã³ã°è¨èªã®å»¶é·ç·ä¸ã«ãããã®ã ãæç¶ãçã»ãªãã¸ã§ã¯ãæåãªããã°ã©ã ã®æ¸ãæ¹ãã§ããããããããã«å ãã¦ãåã«ãããã°ã®çºè¦ãé常ã«ãã¯ãã«ã§ãã¾ãé¢æ°ç(immutableãªãã¼ã¿æ§é ãé«éé¢æ°ã使ã£ã)ããã°ã©ãã³ã°ãåºç¤ã«è¨è¨ããã¦ããããä½ãã¨ã¹ãããªãã¦ããè¨èªãªã®ã ã
ãã°ãä½è«
ä¸ã®ä¾ã«ã¯ãMapã«ç©ºãªã¹ããæ®ã£ãã¾ã¾ã«ãªãã¨ãããã°ããããããã¼ã«ä½¿ã£ã¦ããã¨ã¡ã¢ãªãªã¼ã¯ãé¡å¨åããããã
ä½è«ã ããã©ãå®ã®ã¨ãã ãã¼ã¹ã®ãããã³ã«ã¯ãã£ã¨è¤éã§ã大åã¯C++ã§æ¸ããã¦ããã æã
ã®ã¢ããªã¯OCamlã§æ¸ããã¦ãããä¸è¨ã®ãããªglue codeãæ¸ããã¨ããããã