2016年5月21日土曜日

Done

ご指名ではないけど久々に書いてみました。OCamlもJSも詳しくないので細かいことは知らない。

DoNe

    module H = Dom_html
    let g x = Js.Opt.get x (fun () -> assert false)
    let o = Js.Opt.return
    let s = Js.string
    
    let _ = H.window##onload <- H.handler (fun _ ->
      Firebug.console##debug (s "DoNe starting");
      let d = H.document in
      let tm = g (d##getElementById (s "todo_time")) in
      ignore
        (H.window##setInterval
           (Js.wrap_callback (fun _ ->
             tm##textContent <- o (jsnew Js.date_now ()##toString ())),
            100.));
      let txt = g (H.CoerceTo.input (g (d##getElementById (s "todo_text")))) in
      let btn = g (H.CoerceTo.input (g (d##getElementById (s "todo_button")))) in
      let ul = g (d##getElementById (s "todo_ul")) in
      btn##onclick <- H.handler (fun _ ->
        let v = txt##value in
        Firebug.console##debug (s ("DoNe adding: " ^ Js.to_string v));
        let li = H.createLi d in
        li##textContent <- o v;
        Dom.appendChild ul li;
        btn##value <- s ("NewDoNe#" ^ string_of_int (1 + ul##childNodes##length));
        Js._false);
      txt##textContent <- o (s "");
      Js._false)
    
    • 今回は「状態渡し」すら要らないので「お絵かき」より簡単。何をさせたかったのかまったくわからない。
    • すでに別の人も指摘しているとおり、以前の「状態渡し」のほうがOCaml上のGUIアプリの実装としては異常。書けないとか言うから反例として書いただけ。OCamlは非純粋関数型なので、普通は副作用(破壊的代入を含む)を使う。FRPを含め、純粋関数型のGUIプログラミングがしたかったらHaskellのライブラリなりElmなり、それ用の適切な道具を使えば良い。
    • 自分から要求した「お絵かき」の「トイプログラム」すら1年もかかって自称FRP(実際にはFunctionalですらない命令型プログラム。哲学とか時刻とか理屈をこねたり過去の値を保存したところで、ユーザから見て命令型の非単一代入であることに何ら変わりはない。ちなみにその保存のしかただとJS処理系がガベコレできないのでメモリリークします。)でしか書けないのに、また他人に実装を要求する正当性は1ミリもない。

    2015年7月7日火曜日

    お絵かきロジック(笑)の続き

    元の話題をすり替えて「カクカクしている」(直線しか引けない、と言いたいらしい)とか難癖をつける奴がいたので、また自分の確認・練習も兼ねて。Firefox推奨。

    open Dom_html
    open Graphics_js
    let () = (* open_graph "" *)
      Js.Opt.iter
        (CoerceTo.canvas (getElementById "canvas2"))
        Graphics_js.open_canvas
    let rec k = function
      | `Up ->
          loop [Button_down] (fun status ->
            moveto status.mouse_x status.mouse_y;
            k `Down)
      | `Down ->
          loop [Button_up] (fun status ->
            k `Up);
          loop [Mouse_motion] (fun status ->
            lineto status.mouse_x status.mouse_y;
            k `Down)
    let () = k `Up
    
    後半は
    let rec k () =
      loop [Button_down] (fun status ->
        moveto status.mouse_x status.mouse_y;
        loop [Button_up] (fun status -> k ());
        loop [Mouse_motion] (fun status ->
          lineto status.mouse_x status.mouse_y))
    let () = k ()
    
    でも良いはず。わかりにくいからやめておくが。