トップ 最新 追記

じじぃの日記、ツッコミ可

Twitter: @jijixi_org
Xbox Live: jijixi

初心者が書いた OCaml 入門
Spotlight tips サイト内リンク集
1970|01|02|
2003|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|11|
2011|05|
2012|01|

2006-03-01 [長年日記]

% [雑談] セブンイレブンでダイエットコークを買うのは何だか悔しい

だって隣に並んでる普通のコーラは 128 円なのよ。 なのにダイエットの方は 148 円だなんてなんか納得いかんじゃないか。

つーか、普通のダイエットコークじゃなくてレモン風味のを置いてくれ、ボトル缶入りの。 それなら文句言わずに買うからさ。

% [雑談][ローカルネタ] 小樽 - 国縫 50km/h 規制

って表示が出てて、なんだかなーと思う。

いや、間違ってるわけじゃないんだけど、小樽から国縫に行く人が高速道路に乗るとは思えないんでね。 そんなことしたら、一体いくらかかるのやら。

本日のツッコミ(全3件) [ツッコミを入れる]

% Zapper [レモンペプシのアルミボトルのなら ポスフールに大量にあるけども(安いし]

% jijixi [レモンペプシはおいしくない……]

% Zapper [うまいじゃん(新派閥誕生]


2006-03-03 [長年日記]

% [game] エイリアンソルジャー、スーパーリプレイ

買って一週間経ってから気付くってのもどうかしてるんだが、ガンスターヒーローズ〜トレジャーボックス〜にはエイリアンソルジャーとガンスターヒーローズのスーパーリプレイが収録されていた。

……恐る恐るエイリアンソルジャーを見る。ヒィッ!?

なんか0移動爆装の使い方がおかしいっすよ? それに何だよ選択武器が、フレイム、フレイム、ランサー、ランサーって、偏りすぎ。 いや、生物にはフレイム、機械にはランサーが最強なのはわかってるけど、どっちもすぐ弾切れする武器だからヌルプレイヤーには無理。 完全にノーコンティニューが前提だな、こりゃ。

いろいろ目から鱗が落ちる攻略方法多し。 蜘蛛の倒し方とかアリエナス。 アルテミスフォースの弾があんな軌道で飛ぶなんて知らなかった。 一生懸命正面から迎え撃ってたわしがバカみたいだ。

ちなみに途中でフレイムを一個ランサーに切り替えるね。 主にセブンフォース楓対策みたいな気がするが。 やっぱセイレーンフォースはランサーが一番か。 でも死にまくってて上限が増えてないと、二つあっても全然足りないんだよな。 三つでもどうだろう。上限増えてないのにランサー三つとかだと、何もできない気がする。

ラスボスは、エネルギー残量ゼロのランサーで倒してた。 なんちゅーか「オレのこの手が真っ赤に燃える」みたいな感じで、手の平かざしてるだけで終了みたいな。 なんて可哀想なんだろ。

さて、次はガンスタの方を見よう。 でもなんか知らんが二種類あって、『スーパープレイ・レッド(HARD)』と『スーパープレイ・ブルー(EXPERT)』ってなってんのよ。 しかもどっちも時間が一時間もある。 あがー、どっちから見たら良いんだ……

% [game] ガンスタ、スーパープレイ・ブルー

わりと普通。 わしがブルー(FIXED SHOT)使いだったってのもあるけど、特にすさまじいと思うような点は無かった。 と言うか、全盛時ならわしもあれくらいはできた。

ゴールデン・シルバーの倒し方だけは、ちょっと感心ものだったかな。 あんなに余裕持って倒せるものだとは知らなかった。

今日はもう眠いんで、レッドは明日見よう。


2006-03-04 [長年日記]

% [game] ガンスタ、スーパープレイ・レッド

やっぱ HARD 以上の難易度だとレッドはツライと思われ。 ラスボスで死にそうになってたし(苦笑

ともあれ、ガンスタのスーパーリプレイはどっちも大してすごくなかったな。 『スーパー』と銘打つほどうまいとは思わない。 これが『スーパー』なんであれば、全盛期のわしも『スーパー』だったよ。


2006-03-06 [長年日記]

% [雑談][C] Lightweight Language C (J)

すばらしい発想。

君は今まで一度としてこれで困ったことがあるか!?

至言ですね(笑

% [雑談] 最近の reddit

ネタ系の submission が受け入れられない空気なのが微妙にツマンネ。


2006-03-07 [長年日記]

% [雑談] 標準Cライブラリの最新版「glibc 2.4」リリース (MYCOM PC WEB)

なんとも微妙なクオリティだな、この記事。

Linuxをはじめとする多くのPC-UNIXに採用されている。

Linux 以外で glibc が採用されてる PC-UNIX って何? 寡聞にしてわしは知らん。


2006-03-08 [長年日記]

% [objc] 【コラム】ダイナミックObjective-C 第27回 ランタイムAPIでさらに動的に(1) - 動的なクラスの作成 (MYCOM PC WEB)

ようやくおもしろくなってきた。 今までの内容は、以前に遊んじゃった部分だったんで、いまいち盛り上がらなかったんだよな。

GCC 4.1 ではとうとう Objective-C++ がサポートされたみたいだし、MacOSX + Cocoa に限らず C++ に動的特性を付加するって方向性でも使えるんじゃないかなあ、とか思う今日この頃。


2006-03-09 [長年日記]

% [Gauche] c-wrapper - A Generic Wrapper for C Libraries

何コレ、ステキすぎる。

サンプルコードに typo があるような気がするのはご愛嬌(笑

% [reddit] 『display links with a reddit toolbar』オプション

今まで「なんのこっちゃ?」と思ってスルーしてたんだけど、今日になってこのオプションをオンにしてみたらビックリした。 そういう仕掛けかあ。

ページによっては邪魔な気はするけどおもしろいね。

% [OCaml][雑談] begin..end 偏重主義

Ruby で { } の代わりに do..end を使う練習をしていたら、OCaml で無名関数使う時なんかにカッコで囲むのまでイヤになってきた。 我ながら考えが偏りすぎ。 ともあれ、そんな気がするんだから仕方ないので、カッコの代わりに begin..end を使いまくるテスト。

(* 普通はこう *)
List.iter (fun x -> print_int x; print_newline ()) [1;2;3;4;5]
(* begin 使うと *)
List.iter begin fun x ->
   print_int x;
   print_newline ()
end [1;2;3;4;5]

……わざと怪しげに書いたせいもあるけどキモいな(苦笑

List.iter
   begin fun x ->
      print_int x;
      print_newline ()
   end [1;2;3;4;5]

こんな感じの方が良いかな? どっちにしても、こんなシチュエーションで begin を使ってるコードは見たこと無いけど。

本日のツッコミ(全1件) [ツッコミを入れる]

% _ [Ruby のように begin .. end ブロックが引数の最後のときは非常に美しいですよね!List.iter ..]


2006-03-10 [長年日記]

% [雑談] 春眠あか(以下略

春の気配がしつつある今日この頃、異様な眠気と戦う日々でございます。

とは言え、最近は歳のせいか『週末に 14 時間くらい寝て寝不足感解消』ってのがなかなかできなくなってきてて困りますな。 どうしても途中で目が覚めちゃう。 寝るのって体力使うのね、ほんと。

ちなみに、わしの一回の睡眠で一番長かった記録は、22 時間くらい。 小学校だったか中学校だったかの修学旅行から帰ってきた日だと思った。 晩飯食ってすぐに撃沈して、目が覚めたら夕方だったんでびっくりしたよ。 と言うか、しばらく朝方だと勘違いしてたし(笑

% [OCaml][Haskell] 暇つぶしに OCaml で Monad っぽいものを書いてみた

いや、いまだに Monad は理解できてないんだけどね。 だから、あくまでもそれっぽく動くような気がするだけの『っぽいもの』ってことで。

いろいろ理想に燃えて(?)オブジェクト使ったりファンクタ使ったりやってたんだけど、結局全部めんどくさくなって、非常にシンプルな形に収束。 どっちみち実用性とかはどうでも良くて、単に『作ってみたかった』だけだから良いんだけど。

ってことで、こんなん。

% cat monad.ml
type 'a t = unit -> 'a

let make proc arg = fun () -> proc arg
let invoke m = m ()

let return : 'a -> 'a t =
   fun a ->
      fun () -> a
let fail : string -> 'a t = failwith

module Operator =
   struct
      let (>>=) : 'a t -> ('a -> 'b t) -> 'b t =
         fun m f ->
            fun () -> invoke (f (invoke m))
      let (>>) : 'a t -> 'b t -> 'b t =
         fun m n -> m >>= (function _ -> n)
   end
include Operator

module IO =
   struct
      let putChar ch =
         make (fun c -> print_char c) ch
      let putStr str =
         make (fun s -> print_string s) str
      let getChar () =
         make (fun () -> input_char stdin) ()
      
      let putStrLn str =
         (putStr str) >> (putChar '\n')
      let rec getLine () =
         getChar () >>=
            begin fun c ->
               if c == '\n'
               then return ""
               else
                  getLine () >>=
                     begin fun cs ->
                        return ((String.make 1 c) ^ cs)
                     end 
            end
   end
% ocamlc -c monad.ml
% ocaml monad.cmo
# open Monad.Operator;;
# open Monad.IO;;
# Monad.invoke begin
     putChar 'H' >>
     putChar 'e' >>
     putStrLn "llo, World."
  end;;
Hello, World.
- : unit = ()

ちゃんと動いてるのかはよくわからん。 IO モジュールの各関数は Hugs の Prelude を参考にしつつ。

ところでこれ書いてて、OCaml で char を一発で string に変換する関数が存在しないっぽいのに気付いてアレ〜と思った。 ざっとリファレンスを眺めた限りでは見つけられなかったんで、String.make 1 c とかやってるけど、なんかキモい。

さっそく begin..end を使いまくってるのはご愛嬌ってことで。 でも、慣れてくると結構良い感じのような気がしてたり (ほんとかよ


2006-03-12 [長年日記]

% [OCaml][Haskell] モナドもどき

この前のやつをもう少しいじってみた。 必要に応じて make や invoke の実装を変えたものを作れるように、Monad.Operator は functor で作るようにしてみたり (意味あるのかは、ようわからん)、sequence や mapM を作ってみたり。 ファイルを二つに分けたんで、ここには貼らずに OCamlMakefile 込みでアーカイブ作った。

ダウンロード

実は、この前書いた時点では IO しか再現できないんじゃないかと思ってたんだけど、実は今のままで案外汎用性あるのかも…って気がしてきた。 少なくとも、も少しいじれば遅延評価リストとか作れそう。と言うかリスト自体は作れるけど、それをいろいろ操作する関数が無い状態って感じ。 ともあれ……

% unzip monad_modoki_20060313.zip
% cd monad_modoki
% make
% ocaml monad.cma
# open MonadIO;;
# let cl = ['h';'e';'l';'l';'o';' ';'w';'o';'r';'l';'d'];;
val cl : char list = ['h'; 'e'; 'l'; 'l'; 'o'; ' '; 'w'; 'o'; 'r'; 'l'; 'd']
# let m = Monad.mapM (fun c -> putChar c) cl;;
val m : unit list Monad.t = <fun>
# invoke (m >> putChar '\n');;
hello world
- : unit = ()

こんな感じで遊べる。


2006-03-14 [長年日記]

% [OCaml][雑談] OCaml にも symbol が欲しいなあ

などと思う。 でも symbol は動的型付けな言語でこそ役に立つんであって、OCaml みたいな言語には必要ないのかも知れない。

とは言え、ハッシュテーブルのキーに使えるようなリテラル表記が簡単な型があっても良いと思うんだが。 文字列をキーに使うと、どうしてもハッシュ計算のオーダーが気になる。 文字列のように見えても実際には単なる ID であるような値ならすっきりするのに。

半分洒落で、polymorphic variant タグ(内部的には単なる数値なのだ)をハッシュテーブルのキーに使ってみたことがあるけど、タグを文字列にしたり(あるいはその逆も)できないのが不便だった。

# open Hashtbl;;
# let ht = create 0;;
val ht : ('_a, '_b) Hashtbl.t = <abstr>
# add ht `hoge 1;;
- : unit = ()
# let k = `hoge;;
val k : [> `hoge ] = `hoge
# find ht `hoge;;
- : int = 1
# find ht k;;
- : int = 1
# `hoge == k;;
- : bool = true

一応 symbol の特性は満たしてる感じではあるんだけどねえ。 動的に生成できないんじゃ、やっぱダメだよなあ……

% [vim][OCaml] omlet.vim : Much better OCaml indentation, and more...

vim 純正の ocaml.vim はインデントの付き方にイマイチ納得いかない部分があるんだけど、その不満を解消してくれるかもしれない vim スクリプト。 しばらく使ってみて評価するつもり。

% [vim][OCaml] 3 タブ同盟のための omlet.vim の設定

omlet.vim はインデントのカラム数のデフォルトが 2 になっていて、shiftwidth なんかの設定を無視してくださるのが残念でならなかったんで、仕方なくスクリプトの中身を探った。 と言うわけで、~/.vimrc に下記のように書いとけば良し。

let g:omlet_indent = 3

他にも g:omlet_indent_struct, g:omlet_indent_match, g:omlet_indent_function, g:omlet_indent_let てなのを設定しておけば、それぞれ固有のインデント幅にできる模様。

% [vim][OCaml] omlet.vim の個人的設定

ざっとスクリプトを眺めて適当に設定してみた。

let g:omlet_indent = 3
let g:omlet_indent_match = 0
let g:ocaml_folding = 1
source $VIMRUNTIME/macros/matchit.vim

基本のインデント幅は 3 にしつつ、match の後はインデントしないのが好みなので、それだけ 0 に設定。 三行目は折りたたみの設定。 こうしておくと、結構綺麗に折りたたんでくれるみたい。

四行目はおまけ。 ファイルタイププラグインが対応していれば、% キーが便利になる。 omlet.vim もそうだし、ruby.vim なんかにも有効。

% [vim][OCaml] omlet.vim その他

あー、folding はあんまし好みじゃないかなあ。 foldmethod=indent の方がすっきりしてる気も。 つか、わしのスタイルと相性が悪いだけかも知れないが。

あと tips。

:call OCaml_switch(0)

…で、編集中の .ml ファイルに対応した .mli ファイルを開いてくれる。 逆でもオッケー。 引数を 1 にするとウィンドウ分割して開く。 適当に map しとくと便利かも。


2006-03-15 [長年日記]

% [雑談][OCaml] 自分が書いた OCaml 入門のページを久しぶりに読み直してみたが……

すげえ適当だな。 文体もごちゃまぜだし、とても人に読ませるために書いてるとは思えん。 ……って言うか、まあ元々人に読ませることはあんまし考えてないんだけどさ。 あれはあのページの冒頭にもあるとおり、テディベアに説明してるだけなんで(苦笑)。 むしろ人に教えるというより、人から教えられたいという狙いの元に書いてる感じ。

ただまあ想定してなかったとは言え、ブックマークしてる人がそれなりにいるみたいなんで、この適当さはちょっと心苦しいところではある。 でも、ちゃんと章立てしたり推敲したり云々ってなるとかったるいしなあ。

ってことで、あれは仕様とする(ぉ〜ぃ


2006-03-16 [長年日記]

% [OCaml][Haskell] リストモナドもどき作成中

この前のモナドもどきを拡張して遅延リストを作ってるところ。 基本部分はだいたいできてて、今は淡々と Prelude.hs から関係する関数を移植してる段階。 わりと土方作業だけど、ついでに Haskell の関数を憶えられるので良し。

結局 make や invoke を差し替えるんじゃなく (>>=) とかを替えなきゃダメだと気付いて、ファンクタはばっさり削ったりとか、monad.ml の方も細かくいじったり。 遅延評価 (実際は関数化だけど) すべきところと、そうでないところを適当に判断しながら、わりと行き当たりばったりで書いてるんで、遅延評価されてるように見せかけて全然遅延してなかったりとか不具合いっぱいありそうだなあ。 つーか、さすがにそろそろテスト書かなきゃダメじゃないかと思うんだが、めんどくさがって書きやしねえ(他人事のように)。


2006-03-17 [長年日記]

% [OCaml] AA折れ線グラフ

今さらっぽいけど。 最初はモナドで書いたらおもしろそうだと思って手をつけたんだが、なんかわけわかんなくなったから止めた(ダメダメ)。 でもせっかくだから、考えてたのと似たようなやり方でかつモナドは忘れ去った方針ででっちあげ。

せっかくだから晒す。

% cat aa_graph.ml
type point = char * int

let list_of_string str =
   let rec proc idx cl =
      match idx with
      | n when n < 0 -> cl
      | n -> proc (n - 1) (str.[n] :: cl)
   in
   let first_idx = (String.length str) - 1 in
   proc first_idx []

let mk_point_list l =
   let c_to_a c =
      match c with
      | 'R' -> '/'
      | 'F' -> '\\'
      | 'C' -> '_'
      | _ -> failwith "invalid charcter."
   in
   let fold_f tp c =
      match tp with pl, max_h, min_h ->
      match pl with
      | x::xs ->
           begin
              match x with ch, height ->
                 let next_c = c_to_a c in
                 let add_h =
                    match ch, next_c with
                    | '_', '\\'
                    | '\\', '\\' -> -1
                    | '/', '_'
                    | '/', '/'   -> 1
                    | _, _       -> 0
                 in
                 let next_h = height + add_h in
                 ((next_c, next_h) :: pl),
                    (max max_h next_h), (min min_h next_h)
           end
      | _ -> failwith "unknown error."
   in
   match l with
   | [] -> failwith "invalid input."
   | c::cs ->
        let start_point = ((c_to_a c, 0) :: []), 0, 0 in
        List.fold_left fold_f start_point cs

let rec draw top bottom plist =
   if top < bottom then ()
   else begin
      List.iter begin
         fun x ->
            match x with ch, height ->
               if height = top
               then print_char ch
               else print_char ' '
      end plist;
      print_newline ();
      draw (top - 1) bottom plist
   end

let main () =
   let arg = list_of_string Sys.argv.(1) in
   let point_list, top_line, bottom_line =
      mk_point_list arg
   in
   draw top_line bottom_line (List.rev point_list)

let _ = main ()
% ocaml aa_graph.ml RCRFCRFFCCRFFRRCRRCCFRFRFF
                  __                                             
                 /  \/\/\ 
 _/\_/\        _/        \
/      \__/\  /           
            \/            

list_of_string みたいなのをわざわざ書いてるのが納得いかんな。 extlib とかにあるかしら?

(追記:アホなミスがあったんで修正)

% [雑談] わしはボーダフォンユーザなわけだが

あれですか、個人情報とかもう諦めた方が良いですか。 あー、キャリア変更してー。

いきなり YahooBB の勧誘電話とかかかってきそうで怖いっすよ。 本気でやりそうだからなー。

% [OCaml][Haskell] リストモナドもどき、まだ作成中

相変わらず Haskell の関数を移植してるモード。 つーか、書いても書いても終わらないんですがー(疲

ともあれ、関数型言語をいじるならリストの操作は欠かせないと思われ、この作業のおかげで Haskell にどんなリスト操作関数があるかわかってきて楽しいことは楽しい。 それに Haskell のコードを読むのにもだいぶ慣れてきた気がする。 でも、きっとまだ全然書けない。

とりあえず、OCaml にハマりすぎてるせいか、見慣れない識別子を見つけるとすぐに上の方を探しにいってしまうのが何ともアレ。 where にはなかなか慣れないよ。 知らない識別子がいきなり出てきてびっくりしてると、すぐ後の where 節で定義されてたとかってのがすごく座りの悪さを感じる。 なんか、くだらないことでびっくりしたりして、お前は小心者かー……みたいな。おどおど。


2006-03-18 [長年日記]

% [OCaml] うわーん、わしのヘタレ〜

昨日の AA 折れ線のコードを見てたら、アホなミス発見してしまってハズカシス。

list_of_string 関数は以下のように直してください...orz

--- aa_graph.ml.orig	2006-03-18 14:01:40.000000000 +0900
+++ aa_graph.ml	2006-03-18 13:51:26.000000000 +0900
@@ -3,7 +3,7 @@
 let list_of_string str =
    let rec proc idx cl =
       match idx with
-      | 0 -> cl
+      | n when n < 0 -> cl
       | n -> proc (n - 1) (str.[n] :: cl)
    in
    let first_idx = (String.length str) - 1 in

要するに入力の一文字目が処理されてなかったっすよー。 ヘタレすぎ。 昨日のエントリも直しといたっす。

% [OCaml] なかなか慣れない let でのパターンマッチ

SML 経由じゃなく、いきなり OCaml に入った人 (わしも含む) はわりと知らなかったりするんじゃないかって気がするんだが、let 束縛でもパターンマッチができるのである。 SML だと val の説明でパターンマッチのことが出てくるんで知らない人はいないと思うけど。 と言うか、SML のチュートリアルを読んでびっくりして、OCaml でも試してみたらできたという。

% ocaml

# type hoge = Hoge of string;;
type hoge = Hoge of string

# let h = Hoge "hoge";;
val h : hoge = Hoge "hoge"

# let Hoge s = h;;
val s : string = "hoge"

# type integer = A of int | B of int;;
type integer = A of int | B of int

# let a, b = A 0, B 1;;
val a : integer = A 0
val b : integer = B 1

# let A i | B i = a;;
val i : int = 0

# let A i | B i = b;;
val i : int = 1

こんな感じ。 タプルから値をバラバラに受け取るような使い方は普通に使ってたけど、これもやっぱりパターンマッチの恩恵だったわけね。 てっきり Ruby のような感じのものだと思い込んでたんで気付かなかった。

そんなわけで、タプルやヴァリアントを単純にばらしたりするときには let を使えば良いんだけど、それを知らずにそういう用途は match でやってた時期が長かったせいか、なかなか慣れないんだよなあ。 match 使うよりコードがきれいだと思うんで、意識して使いたいとは思ってるんだけども。


2006-03-19 [長年日記]

% [OCaml] Warning P: this pattern-matching is not exhaustive.

soutaro さんとこで言及されてましたが。 もちろんこの警告はウザいので、そういうときは素直に match 使います。 だから当然リストにも使わないですな。

わしが主に "使おう" と思ってるシチュエーションは、

type hoge = Hoge of int * string;;
let h = Hoge (1, "hoge");;
let Hoge (i, _) = h;;

こういう場合ですね。

あと、これはあんまり無さそうだけど、variant 型の中で必ず出てくる型ならパターン不足の警告は出ないので、

type fuga = A of int | B of int * string | C of int * int * string;;
let fu = A 0;;
let A  i
  | B (i, _)
  | C (_, i, _) = fu;;

こんなことはできます。

% [OCaml] let でパターンマッチのさらに変態的な使い方を思いついた(笑

こういうのはどうでしょう。

# type t = A of string * int;;
type t = A of string * int

# let a, b = A ("hoge", 0), A ("fuga", 1);;
val a : t = A ("hoge", 0)
val b : t = A ("fuga", 1)

# let A ("hoge", i) | A (_, i) = a;;
val i : int = 0

# let A ("hoge", i) | A (_, i) = b;;
val i : int = 1

ネタのつもりで考えたけど、場合によっては使えるシチュエーションあるかも……いや、無いな(苦笑

% [OCaml][Haskell] リストモナドもどき

一応完成。テストは足りないけど、そこまでやる気にならん(苦笑

ダウンロード

わりと遊べるものになったような気がするんで、暇な人はどーぞ。 特徴としては…

  • 遅延リストである。
  • Haskell 互換っぽい (操作関数は Hugs の Prelude.hs からベタ移植)。

向井さんの LazyList に対抗してるわけじゃないけど (あれは OCaml の List 互換だと思われ)、元々モナドのネタから始まったんで自然と Haskell のマネになってる。 おかげで Haskell のリスト操作関数は結構憶えられた気がする。

主立った関数は Haskell 互換だから説明はしないけど、基本部分は軽く説明しとく。 基本的に Haskell から持ってきたものは同じ動きになるようには作ってあるつもり。 ただし、リストではなく値を返す類の関数で、無限リストを与えると帰ってこなくなりそうなもの (fold 系など) にはリミット値を設定してあり、かつ Monad.t で包んで返すようにしてある。 まあ、詳細はソースを見てもらうと言うことで。

type 'a cell = Null | Pair of 'a * 'a t
and 'a t = 'a cell Monad.t

val null_list : 'a t
   [] に相当する定数
val cons : 'a -> 'a t -> 'a cell Monad.t
   cons x xs は x :: xs に相当
val new_cons : 'a -> 'a cell Monad.t
   a :: [] に相当

val list_limit : int ref
   無限ループしそうな関数ではこの値を使って例外を起こさせてる
   リファレンスなんで、変更可能

type ('a, 'b) generator_proc = 'a -> 'b option * 'a option
   generate 関数で使うジェネレータ関数の型
   元になる値を引数に取り、生成した値と次に呼ばれる時に使うための値を返す
val gen_proc_default : ('a t, 'a) generator_proc
   リストから順に値を出していくだけの generate 用関数
val generate : ('a, 'b) generator_proc -> 'a -> 'b t
   ジェネレータ関数からリストを作る関数
val generate_with_filter :
  ('a, 'b) generator_proc -> 'a -> ('b -> bool) -> 'b t
   generate のフィルタ付き版

val range : int -> int -> int -> int t
   Haskell の [n, m..o] と同じ働き (のはず)
val range_inf : int -> int -> int t
   range の終わりの値を指定しないバージョン
val range1 : int -> int -> int t
   増分が 1 に固定の range
val range1_neg : int -> int -> int t
   増分が -1 に固定の range
val range1_inf : int -> int t
   range1 の終わりを指定しないバージョン
val range1_neginf : int -> int t
   range1_neg の終わりを以下略

val of_list : 'a list -> 'a t
   list から MonadList.t へ
val to_list : 'a t -> 'a list
   MonadList.t から list へ
val to_list_rev : 'a t -> 'a list
   to_list の結果が逆さまになるけど、こっちの方が速い
本日のツッコミ(全1件) [ツッコミを入れる]

% 向井 [letって複数のパターンを書けたんですね。知らなかった。 let `A ("hoge", _) as x | `A(..]


2006-03-20 [長年日記]

% [OCaml][Ruby] renamemodule.rb (soutaroにっき)

便利そうなのでもらっておこう。

そういや pathname モジュールって存在は知ってるけど使ったこと無いなあ。 方向性は良いんだけど、イマイチわしが求めてるのと違うと言うか……

ちなみに Ruby 標準のファイル命名規則は好きくない。 キャメルスタイルでもアンダーバーでも良いから、区切りは合った方が良いと思うんだけどね。 まあ、わしはわりと余裕で無視してるが (広く使われることを意識してないからって話もある)。

% [雑談][ツッコミ] さりげなくツッコミにまとめて遅レス

切なくたって、わしは begin .. end を使うんだい。 やっぱ複数行のブロックをカッコで済ますのはイヤなのです。今の気分では。 なんとなく、こんな風に書けば良いような気がしてきた。

List.iter
   begin fun x ->
     print_int x;
     print_newline () end
   lst

……ごめんウソ、言ってみただけ。 キモすぎます。

let でパターンマッチのカッコイイ使い方は思いつきませんですた。 や、パターン不足の警告が出てもガマンするなら、なんかありそうな気もするんだけど……

本日のツッコミ(全3件) [ツッコミを入れる]

% _ [こ、この記法はッッ!!!かつて Rubyist を震撼されたアレじゃないですか! http://www.paulgr..]

% jijixi [わはは、キモい。 たぶんこれ、Common Lisp の例を単純に直しただけっすね(笑]

% _ [sed か何かで置換したに一票っ]


2006-03-22 [長年日記]

% [雑談] Q. スタックとキューの違いは何か

…に対する答え。

「どちらかがFIFOで、どちらかはLIFOです」

[sumiiの日記より引用]

とんちのセンスがあると見た(謎

% [game] 零三

零〜刺青の聲〜』というのを友達に借りてやってたんだが、予想外にハマってしまって前作前前作を買ってしまったよ。

だって、主人公が三人いるんだけど、そのうち一人が一作目の主人公で、もう一人は二作目の主人公の叔父だったりすんのよ。 気になりすぎるって(苦笑)。 舞台が夢の中のせいか、一作目と二作目の舞台まで混じってるみたいだし。

何と言うかこう…無駄なサービスシーンとかある系のアレな作品なんだろ?みたいな感じで敬遠してたんだが、バイオ系のホラーゲームとしてかなりよくできてると思う。 少なくとも三作目はそうだった。一作目、二作目はこれからなんでわからんけど。

いや、まあね、案の定無駄なサービスシーンはあったけどね。 シャワーシーンとか脈絡無さ過ぎる。 それどこの B 級ホラー?(笑

あとラスボスが即死攻撃してきたり、ゲームバランスに理解しがたい部分があったりもするけど、全体的にはよくできてる。 やり込み要素もあるし。

バイオと言うよりサイレントヒルシリーズが好きな人にお薦めしたい。 つーか、刺青の聲は妙にサイレントヒル4と設定がかぶってたりして。

% [game] 零一と二

とりあえずさわりだけやってみる。

……わ、いきなり見たことある場所だし(笑

なるほど、一作目、二作目を経験済みで三作目をやると、見たことある場所が出てきて「おお〜」となる仕掛けだったのね。 なんか損してる気になるな……

% [game] 零日記

刺青の聲をやってて、「今どき黒電話は無いだろ」とか思ってたんだが、一作目が 86 年の話だったのか。 とすれば三作目もそれから数年しか経ってないんだろうから、まあアリかねえ。

いや、あのジリリリって鳴る電話は結構良いビックリドッキリアイテムなんだけどね(苦笑)。 サイレントヒル辺りでも結構使われてるし。

% [Firefox][Mac] Bon Echo 2.0a1 の Mac 版を試してみた

なんか懸案だったフォントの扱いが改善されてるっぽい。 これは良いかも。

使ってる機能拡張が対応したら、X11 版から乗り換えられるかな。 まあ、まだまだ先だと思うけど。

% [game] 零一日記

ふむ、一作目からわりと完成されてるっぽいな。

それにしてもお前はなぜそんな無駄にスカート短いのかと問い詰めたい。 いや、キュロットなのかも知れんが、どっちにしても見知らぬ山ん中の幽霊屋敷に乗り込むぞって時に、そんな軽装で来るヤツがおるかと小一時間……

そこら辺がぱっと見、ゲーム内容を安く見せてしまう要因だと思うんだがなあ(苦笑

% [OCaml] ところで、OCamlって[1..10]みたいな書き方はどうすればいいんだろう?

ぎゃわー、超痛いところを突かれてるんじゃよー!!

……えーと、強いて言えば、

# Array.to_list (Array.init 10 (fun i -> i));;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]

みたいな? ……ダメすぎ...orz

いやあ、なんつーか、正格評価だとなかなか定量的なリスト生成法って無いんじゃないかと。 だからまあ、シチュエーションに応じて実装しなさいよーつー親心なんじゃないかなーとか勝手に良い方に解釈してみたり。 ……計算量とかどーでも良いから、簡単な記法が欲しいよっつー欲求は確かにあるんだけども(苦笑

OCaml がスクリプト言語として台頭するには、まだまだ道は遠いのであった(ガックリ

あとはまあ、camlp4 を使うことを許容するなら mmatsuoka さん作の Pa_list を使うのも手。


2006-03-23 [長年日記]

% [OCaml] 昨日の続き

いや、なんか布団の中とか車の中とかで悶々と考えてしまって(苦笑

比較的広範囲でそれなりの性能を発揮するリスト生成法はどんなかなーと考えるに。 昨日書いた array 作って list に変換てのはわりと安定した性能な気がするんだけど、あれって要素数がわかってないといかんので、そうじゃない場合は微妙になってくる。

そうすっとやっぱ要素数の縛りが無い構造を利用するのが良いのかーってことになって、結局 Pa_list がやってるように Stream を使うのが正道なのかしらん。

Stream は、うっかり iter とか next とか使っちゃうと余裕で破壊的動作をしてくれるんで (特に iter は切ない) リファレンスの最後の四つ (peek, junk, count, npeek) 以外は使わない方が良いんじゃないかと思われ。 つーか個人的には njunk みたいなのも欲しい。

ちなみに ExtLib には Enum っていうデータ構造があって、なんつーか Stream と List の中間みたいなもんでぶっちゃけ遅延リストなんだけど、これがまた (前に向井さんが書いてた気もするけど) Stream と同じように iter で中身がすっからかんになっちゃうのが切なすぎる一品だったりして、なんか最近ちょろちょろ ExtLib のソース眺めたりしてるんだけど、どうにも趣味に合わないんで使う気に慣れなかったりとか。 なんかわけのわからん愚痴になってしまった。

なんでこんな話になったんだっけ? あーそーそー、やっぱリスト生成が便利な状況って、そのリストは遅延リストの方がありがたい場合が多い気がするのよね。 と言うか、結局正格リストを作ると言っても遅延リストを作って変換って流れになってしまうわけで、なら遅延なまま使った方が良かろうと。

なんだけども、なんつーか広く使われてる実装で、かつ好みに合うようなのが無いってのは困ったもんだなあと思うわけで。 向井さんの LazyList だって広く普及してるとは思えないし、わしのアレなんてさらにダメだし。

いや、どうせ広く公開するようなものを作るわけじゃないんだから、変にライブラリにこだわる必要も無いんだけど……

% [OCaml][Haskell] リストモナドもどきを書いたおかげで、なんとなく遅延評価のありがたみがわかってきた気がする今日この頃

なんつーか、あれを書いたことによる実用上の恩恵は特に無いわけだけど (遅延リストなら、すでに LazyList があるわけで) 、元々 Haskell の勉強のためにやってたことなんで、それについてはわりと役立ったなと思う。

まあ、いろんなところで読んでいた事ではあるんだけど、『やりたいことを素直に書ける』ってこと。 それを理論じゃなく実感として感じられた気がする。

Hugs のコードを参考にしながら書いてて驚いたのが、末尾再帰が全然出てこないことだった。 たぶん末尾再帰にできる箇所も結構あったと思うんだけど、そもそもそういう細かい事を気にする必要が無いんだと気付いた。 正格評価な脳で見ると、いかにもスタック溢れそうに見えるんだけど、実際には結果のリストから要素を一つ取り出すごとに一回ずつ再帰するだけなんだよね。 要するに、正格評価だと非常にコストがかかる処理でも、なんとなく負荷が分散されて何とかなってしまうような感じ。

OCaml な人は多分リスト同士を連結したいときに、(@) を使って良いかどうかを一瞬でも考えると思うんだけど、Haskell な人は多分考えないんだろう。 リストを連結したいんだから、素直に (++) を使えば良いんだと。 たしかに、いちいち何かする度に「スタック溢れないかな?」って心配して、場合によってはそれを回避した別のやり方にしたりするってのは、直感的じゃないわな。 まあ、普通の正格評価な言語に慣れちゃってる人は、そういう考え方にも自然と慣らされちゃってるんだけど(苦笑

そんなわけで、あれだ。 今まで何とか『遅延評価を理解しちゃろう』と気張ってたわしは間違ってた。 遅延評価と付き合うにはどうしたら良いかっつーと、つまり『細かい計算コストとか無視』、コレだ。 富豪的プログラミング万歳。

そんなこんなで Haskell に親しみが持ててきた気がするわしであった、マル。

% [本日のリンク元] Yahoo!検索 (鋼鉄ジーグ 死ねぇ)

誰だ、こんな検索してくるやつは(笑

乙だ、死ねぇ!

本日のツッコミ(全4件) [ツッコミを入れる]

Before...

% jijixi [ありゃ、そうだったんすか(汗 いやあ、camlp4 のソースはいまだにろくに読めないんで(苦笑 Stream モジュ..]

% k.inaba [例えばリストの逆転を、末尾再帰になってないことや(++)を使ってることなど気にせず rev [] = [] rev ..]

% jijixi [ああ、なるほど、何事も万能の剣ってのは無いもんですね。 『まったく無視するわけにはいかないけど、正格評価よりはわりと..]


2006-03-24 [長年日記]

% [雑談][PC] csv ファイルをいじってたら……

ストレス溜まるよね。

故あって、Ruby の CSV モジュール使ってごにょごにょやってたんだけど、なんかこう……なんつー貧弱なデータ構造なのかと思ってぐったりしたのであった。 「もう、この際テキスト形式のデータ構造は全部 S 式にしてしまうのが吉なんですよ」と天の声が聴こえた気がしたが、幸か不幸かまだそこでウンとうなずくほどには、わしの頭は Lispy になっていなかったようだ。

いやね、要するに表計算ソフトとの橋渡しができれば良いだけだから、別に機能はこれでも良いのよ。 XML とかいじりたくないし。 でも、ちゃんとした規格が無いせいで、アプリケーションによって扱いがいちいち違うのがうんざりするんだよね。 例えば OpenOffice.org で csv ファイルを吐かせると…

"hoge","fuga","foo","bar"

みたいに、データをダブルクォートで挟んだ形で出てくるんだけど、Ruby の CSV モジュールはこれを読めなかったりすんのよね。 そういう細かい互換性の問題をちまちま考えながら作業すんのは、ものすごくストレス溜まるんだよ(疲

% [reddit] rising ?

いつの間にか "rising" って項目ができてるけど、何だろこれ? "hot" と何が違うんだろ。

% [OCaml] AltStream.ml

何となく暇つぶしで書いてみた Stream モジュール互換の非破壊的ストリームモジュール。 つっても単にオブジェクトで包んで、破壊的操作をしたときには次の操作のときにその都度作り直してるという、非常にどんぶり勘定な代物。

や、片手間のネタですから(笑

from や of_list の代わりに from' や of_list' で immutable なのが作成される。 貼るにはちょっと長い気もするけど、めんどくさいんでやっぱ貼る(ぉぃ

% cat altStream.ml
class ['a] istream (f : int -> 'a option) = object (self)
   val proc = f
   val mutable stream = Stream.from f
   val mutable destructed = false
   method refresh = stream <- Stream.from proc
   method private check = if destructed then self#refresh
   method private destruct = destructed <- true
   method getProc = proc
   method getStream = stream
   method is_immutable = true
   method is_mutable = not self#is_immutable

   method iter f =
      self#check;
      let r = Stream.iter f stream in
      self#destruct;
      r
   method next =
      self#check;
      let r = Stream.next stream in
      self#destruct;
      r
   method empty =
      self#check; Stream.empty stream
   method peek =
      self#check; Stream.peek stream
   method junk =
      self#check;
      let r = Stream.junk stream in
      self#destruct;
      r
   method count =
      self#check; Stream.count stream
   method npeek n =
      self#check; Stream.npeek n stream
end

class ['a] mstream (s : 'a istream) = object (self)
   inherit ['a] istream (s#getProc)
   method private check = ()
   method private destruct = ()
   method is_immutable = false
end

type 'a t = IStream of 'a istream | MStream of 'a mstream

(* Stream module compatible *)
(* Stream builders *)
let from ?(immutable = false) f =
   let s = new istream f in
   if immutable
   then IStream s
   else MStream (new mstream s)

let of_list ?(immutable = false) l =
   let a = Array.of_list l in
   let f i =
      try
         Some a.(i)
      with Invalid_argument _ -> None
   in
   from ~immutable:immutable f

let of_string ?(immutable = false) s =
   let f i =
      try
         Some s.[i]
      with Invalid_argument _ -> None
   in
   from ~immutable:immutable f

let of_channel ?(immutable = false) ch =
   let f i =
      try
         seek_in ch i;
         Some (input_char ch)
      with End_of_file -> None
   in
   from ~immutable:immutable f

(* Stream iterator *)
let iter f s =
   match s with
   | IStream o
   | MStream o -> o#iter f

(* Predefined parsers *)
let next s =
   match s with
   | IStream o
   | MStream o -> o#next

let empty s =
   match s with
   | IStream o
   | MStream o -> o#empty

(* Useful functions *)
let peek s =
   match s with
   | IStream o
   | MStream o -> o#peek

let junk s =
   match s with
   | IStream o
   | MStream o -> o#junk

let count s =
   match s with
   | IStream o
   | MStream o -> o#count

let npeek n s =
   match s with
   | IStream o
   | MStream o -> o#npeek n

(* for AltStream *)
(* make immutable stream, but ad-hoc :-p *)
let from' f = from ~immutable:true f
let of_list' l = of_list ~immutable:true l
let of_string' s = of_string ~immutable:true s
let of_channel' ch = of_channel ~immutable:true ch

let is_immutable s =
   match s with
   | IStream o
   | MStream o -> o#is_immutable

let is_mutable s = not (is_immutable s)

let obj_copy o =
   let new_o = Oo.copy o in
   new_o#refresh;
   new_o

let copy s =
   match s with
   | IStream o -> IStream (obj_copy o)
   | MStream o -> MStream (obj_copy o)

let to_immutable s =
   match s with
   | IStream o -> IStream (obj_copy o)
   | MStream o -> IStream (new istream o#getProc)

let to_mutable s =
   match s with
   | IStream o -> MStream (new mstream o)
   | MStream o -> MStream (obj_copy o)

let get_raw s =
   match s with
   | IStream o
   | MStream o -> o#getStream

let get_proc s =
   match s with
   | IStream o
   | MStream o -> o#getProc

let refresh s =
   match s with
   | IStream o
   | MStream o -> o#refresh

let to_list ?(length = 10000) s = npeek length s

% [OCaml] オプショナル引数

存在は知ってたけど、上の遊びで初めて使ってみた。 最初、

Warning X: this optional argument cannot be erased.

っていう警告に激しく悩まされる。 と言うのも、Ruby にしろ C++ にしろデフォルト値を設定した引数ってのはケツに来るもんだから、思いっきりそのつもりでやってたよ。

でも、OCaml ではオプショナル引数は通常の引数の手前に無いとあかんのであった。 まあ、考えてみれば、そうじゃなきゃ関数呼び出しのときに引数を省略してるのか部分適用しようとしてるのか区別がつかないもんね。 そりゃそうだ。

% [OCaml] だから let でパタ(略

しまったー!! こういうときこそ使えというのに、まったくわしはー...orz

let refresh s =
   let IStream o | MStream o = s in o#refresh

% [game] 零一クリア

三の例から考えると拍子抜けするほどにラスボスは楽だった。 …んだが、倒した後の良いところでフリーズすること二回。 くそ、このバグ持ちめ。 ある意味こっちの方がタチ悪い(疲

これで二でもラスボスで何かしらハマったら、そういう伝統だと諦めるしかないのか? 嫌な伝統だな、おい。

ともあれ、ラスボス以外は三よりつらかった。 敵がよく見えないんだもん。 ダメージ食らうと一発がでかいし。 回復アイテムも少なくなってきてて、これでラスボスまで鬼強だったら、コントローラーぶん投げるところだったよ(苦笑

ともあれ、普通におもしろかった。 さて、今度は二へ移行すんべ。

% [OCaml] AltStream を目デバッグ中

refresh メソッドで、destructed を false に戻す処理入れるの忘れてるから、チェックの意味無ぇーー...orz

やっつけ仕事ばっかしてるから、もう。


2006-03-25 [長年日記]

% [OCaml][Haskell] Clean入門(15):正格性

正格評価と遅延評価の関係についてすごく参考になった……気がする。

んで、いきなり微妙に関係無い話に移るけど、結局計算機資源が有限である以上、どこかには気を付けなきゃならん箇所があるんだよなあ、と。 正格評価どっぷりな人が遅延評価の利点とかを垣間見ると、なにやらスゴイもののように感じちゃうけど、裏を返せば逆に思いもよらないところで皺寄せが来たりとかってことになるのかも知れん。

そんなわけで、実は Concurrent Clean ってすごい言語なのかも…って気がしてきたが、やっぱりよくわかんないうちに正格と非正格が混じっちゃうような環境は、ちょっと怖い気もしてなかなか手を出す気になれない小心者のわしであった。


2006-03-27 [長年日記]

% [雑談] 低調でまったり

あーやる気出ね……

唐突に skk が恋しくなって、MacUIM とか入れてみたり。 でも uim-xim が含まれてないから、fink でも uim 入れたり。

なんかそんな、どーでも良いような作業とかをだらだらと……はぁ……

% [まんが] おお振りページ多すぎ(笑

六巻には四ヶ月分しか入ってなかったので、桐青戦が決着するのは八巻だと思われ。 毎月 70 ページ前後って気合入りすぎだよな。 決着時の回なんて 80 ページもあったぞ。

いや、読む方としては読み応えあって良いんだけどね(苦笑

本日のツッコミ(全1件) [ツッコミを入れる]

% TrackBack [http://jijixi.azito.com/cgi-bin/diary/index.rb?date=200604..]


2006-03-28 [長年日記]

% [雑談][Ruby] 最高にキモい Ruby コードを書いてみよう

この辺に触発されてみるテスト。

def f
   lambda do |x|
      x.each do |i|
         p i end end end

f.call ["hoge","fuga"]

lisper の気持ちになってみた (怒られるぞ) 。 カッコの代わりに end を使うなら end の場所はここしかない!!

% [uim][Scheme] uim-sh

ふと気づくと uim-sh ってコマンドが存在するのであった。 何かなーと思ってとりあえず呼んでみる。

% uim-sh
uim>

む…

uim> (define hoge '(1 2 3))
(1 2 3)

どう見ても Scheme インタプリタです。本当に(略

そういや uim って設定ファイルが Scheme だったっけ。 そこら辺のデバッグに使うんだろな。 ちなみに調べてみると siod ベースらしい。 またお前か!!

そんなことより、カッコが全角で入力されちゃうのが切ないので何とかせにゃならん。 ここ見ながらちまちまがんばろう。 っつーか、以前この辺設定した気がするんだけど、設定ファイルはどこ行っちゃったんだろなあ...orz

% [uim] ローマ字入力の設定

/sw/share/japanese.scm から関係箇所パチってでっちあげ。

% cat ~/.uim
(require "japanese.scm")
(define ja-rk-rule
  (append '(
            ((("!"). ())("!" "!" "!"))
            ((("\""). ())("\"" "\"" "\""))
            ((("#"). ())("#" "#" "#"))
            ((("$"). ())("$" "$" "$"))
            ((("%"). ())("%" "%" "%"))
            ((("&"). ())("&" "&" "&"))
            ((("'"). ())("'" "'" "'"))
            ((("("). ())("(" "(" "("))
            (((")"). ())(")" ")" ")"))
            ((("^"). ())("^" "^" "^"))
            ((("\\"). ())("\\" "\\" "\\"))
            ((("|"). ())("|" "|" "|"))
            ((("`"). ())("`" "`" "`"))
            ((("@"). ())("@" "@" "@"))
            ((("{"). ())("{" "{" "{"))
            ((("+"). ())("+" "+" "+"))
            (((";"). ())(";" ";" ";"))
            ((("*"). ())("*" "*" "*"))
            (((":"). ())(":" ":" ":"))
            ((("}"). ())("}" "}" "}"))
            ((("<"). ())("<" "<" "<"))
            (((">"). ())(">" ">" ">"))
            ((("?"). ())("?" "?" "?"))
            ((("/"). ())("/" "/" "/"))
            ((("_"). ())("_" "_" "_"))
            ) ja-rk-rule))

基本的に記号は半角でという方針。

本日のツッコミ(全2件) [ツッコミを入れる]

% 向井 [設定というか uim の変換エンジンのロジックはぜんぶ scheme で書かれてますよ。]

% jijixi [ありゃま、そうだったんですか。 じゃあ追加機能とかも Scheme で書けるんすね。それは楽しそうだ。]


2006-03-29 [長年日記]

% [雑談] PEPSI NEX

なかなか良い。 すでに今日一日で 3 本飲んだ(ぉぃ


2006-03-30 [長年日記]

% [OCaml][Haskell] 型クラスの素人話

モナドもどきとかの絡みで Haskell のコードとかちょろちょろ読んでたせいか、なんとなく型クラスがどういうもんかわかりかけてきた気がした。 気がしただけかも知れないが。

なんつーのか、細かい部分は当然違うんだろうけど、大体の線で言って……

Haskell の class は OCaml の functor で、instance は functor から作られる module みたいなもん。

……かな、と。 つか、そう考えるとなんとなく Haskell のコードが読みやすくなった感じがしたんで、たぶん当らずとも遠からずなのかなという気がするだけなんだけど。

Haskell は関数オーバーロードがあるから、各インスタンス (OCaml で言えばモジュール) の関数が平らな名前空間で使われてしまうのが混乱するところではあるけど、まあ、その都度 open して使ってると思えばなんとかならなくもない。

ところで、まだわしは functor を本格的に使った事無いんだけど、ちょろちょろ実験的にいじってる感じでは、functor 使うならオーバーロードが欲しいな……みたいな、ちょっとポリシーに反した感想を持ってしまったりする。 ってことは、実は Haskell のオーバーロードは、型クラスを使い易くするために導入されてるんだろうか?などと思ったりもした。 や、妄想だけど。

% [game] まったり A.C.E.2 をやっとった

あー、適度にヌルい難易度でまったりしてて良い。 それにしても、今回使える機体が 80 以上とか書いてあって、ぉぃぉぃ…と思ったり。 まあ、同じ機体でパイロットが違うっていうバリエーションがあるから、そのくらいにはなるのかも知れないが。

それにしても、連係攻撃がスパロボの合体攻撃みたいで楽しいんだけど、いかんせんゲージが溜まるのが遅くてあんまり回数使えないのがせつない。 チャクラエクステンションはイベントで使いまくったんだけどなあ。 そういうイベントでも無いと、ほとんどの面でゲージ溜まるより先にクリアしてしまったり、溜まってもせいぜい一回こっきりだったり。 威力低くて良いから、もっとバンバン使えるバランスにしてほしかったなあ……

% [game] ACE2 日記

いきなり現われたドモンが無限軌道砲を破壊して、「おまえら、この男を知ってるか」とおよそ場違いな因縁まがいの質問を付きつけたあげく、知らないと答えたら「おまえらに用はない」とゴッドフィンガーかましてゴル死亡。 ゴルさんの出番これだけ(せりふ無し)。

でもジンなんてセリフどころか機体すら出なくて、そもそも存在が黙殺されてるから、それにくらべれば良い方だ。 そのくせグンジェムはやたらカットインがいっぱいあって何だかなーつー感じだが(笑

まあ、ジンの機体はスパロボ MX だと EWAC(強) が付いててウザさ満点だから、いつも優先撃墜目標になるわけで、きっとそんな感じで見えないところで速攻で落とされてたに違いない。

% [game] ACE2 日記 2

地味なネタが微妙にツボ。 ドモンのゴッドガンダムを見てガイが…

「あれがモビルファイターか。くぅ〜俺も一度乗ってみたいぜ!!」

とか言ってて噴く。 ある意味、君乗ってるでしょ、みたいな(笑


2006-03-31 [長年日記]

% [OCaml] AltString (まださわりだけ版)

Camomile を使う練習として、WSCstring みたいな仕組みを作ってみようと思って書いてみた最初の段階。 初めて Camomile を使った (というか、使おうとしたが挫折した) ときは、はっきり言ってどうやって使ったら良いのかさっぱり理解できなかったんだが (その頃は functor とか全然わかってなかったから…)、当時よりそれなりに OCaml に慣れた今見ると、Camomile はかなりカッコイイ作りだなーとか思った。

% cat altString.ml
open Camomile

(* internal string type *)
module IString = UTF16
module Enc = struct
   include CharEncoding.Make (IString)

   let jauto = CharEncoding.of_name "jauto"     (* auto detection *)
   let eucjp = CharEncoding.of_name "EUC-JP"
   let shiftjis = CharEncoding.of_name "Shift_JIS"
   let iso2022jp = CharEncoding.of_name "ISO-2022-JP"
   let utf8 = CharEncoding.utf8

   let default : CharEncoding.t option ref = ref None
end
module Sub = SubText.Make (IString)

exception Not_initialized     (* no use *)
exception Already_initialized

let module_initialize ?(default = Enc.eucjp) () =
   match !Enc.default with
   | None -> Enc.default := Some default
   | Some _ -> raise Already_initialized

let change_default_encoding enc =
   match !Enc.default with
   | None -> module_initialize ~default:enc ()
   | Some _ -> Enc.default := Some enc

let rec get_default_encoding () =
   match !Enc.default with
   | None -> module_initialize (); get_default_encoding ()
   | Some enc -> enc

class mbString enc str = object (self)
   val nStr = String.copy str
   val uStr = Enc.decode enc str
   method getStringOf e =
      if e == enc
      then nStr
      else Enc.encode e uStr
   method getString = self#getStringOf enc
   method convertTo e = new mbString e (self#getStringOf e)
   method length = IString.length uStr
   method get idx = IString.get uStr idx
   method sub start len =
      let r =
         Sub.excerpt (
            Sub.refer
               uStr (IString.nth uStr start) (IString.nth uStr (start + len)))
      in
      new mbString enc (Enc.encode enc r)

   initializer
      ignore (get_default_encoding ())    (* it's trick :-p *)
end

type t = mbString

let of_string ?(enc = get_default_encoding ()) str =
   new mbString enc str

let to_string ?(enc = get_default_encoding ()) mbs =
   mbs#getStringOf enc
% cat Makefile
SOURCES=	altString.ml
LIBS=		camomile
INCDIRS=	$(shell $(OCAMLFIND) query $(LIBS))
RESULT=		altString

all: bcl

include OCamlMakefile
% ocaml
# #use "topfind"
# #require "camomile"
# #load "altString.cma"

# let s = "\164\219\164\178\164\213\164\172";;
val s : string = "ほげふが"

# let alts = AltString.of_string s;;
val alts : AltString.mbString = <obj>

# alts#length;;
- : int = 4

# let sub = alts#sub 2 2;;
val sub : AltString.mbString = <obj>

# AltString.to_string sub;;
- : string = "ふが"

なんとなく今回は副作用が無いオブジェクトとか作ってみたけど、なんかすごく不経済な感じ(苦笑

それはそれとして、最近の好みの傾向として OCaml でオブジェクトを直接操作させるのはイケてない感じがしたりしてるので、もしこのまま作り続けるとしたら、やっぱりこの前の AltStream みたいに基本的にはオブジェクトは隠蔽して関数で操作するようになっていく予感。

% [雑談] 枯れた技術 != 古い技術

言及ってほどのもんではなく、単に触発されて頭に浮かんだ話をたらたらと。

枯れた技術ってのは単に古いってことではなくて、たくさんたくさん使い込まれて問題となる部分がきっちり洗い出されてるもののことを言うと思うのですよ。

未知の不具合が存在しない (…と言うか、存在の可能性を無視できるほどに十分な使用例がある) っていうのは、『道具』というものにとっては大事ですね。 遺伝子組み替え作物が (少なくとも今は大きな問題が発見されてるわけじゃないのに) 危険視されるのは、そういう未知の不具合の存在を否定しきれないからなわけで。

まあ、そういう論法がプログラミング言語やコンピュータ関係の技術に素直に当てはまるのかっていう疑問が無いことは無いですが。 どっちにしても、無条件で枯れたものをありがたがるのもダメなら、同じように無条件で新しいものをありがたがってもダメで、結局は重視する条件に応じて選択をするしかないのです。 メリット、デメリットを把握せずに、ノリだけで使う道具を選んじゃいけませんね。

% [game] ACE2 日記 3

やっぱり今回も、フィンファンネルは一回飛ばすと撃ち落とされて戻ってこないのであった...orz

クライマックス U.C. のνガンダムは結構強いのになあ。 ACE のはフィンファンネルが全くあてにならないから、単にちょっと性能の良いモビルスーツでしかない。 そういや前作のキュベレイは極悪だったっけ。 今回は出ないと思うけど。

% [OCaml] pa_macro (晩ごはんの履歴)

ごにょごにょ計算した値を let 束縛して、それと一致するかをパターンマッチで検査とかやろうとしてハマった過去を思い出した。 switch-case とは違うんだ。case-when とは違うんだーー...orz

そんなこんなで、自然と考え方そのものがそっちに行かなくなってる今日この頃であった。 なので、便利そうだなと思いつつ、あまりありがたいと思わなかったり。 つか、わしのハマったシチュエーションだと、これ使っても回避できないのかな。 (その都度、束縛の代わりに DEFINE すれば良いのかも知れんが、それは何か違う気が……)

ちなみに、リンク先のようなシチュエーションだと、わしなら…

# let get_num op =
     match op with
     | `NOP  -> 0
     | `PUSH -> 1
     | `POP  -> 2
     | `ACC  -> 3
     | `ADD  -> 4
     | `HALT -> 5
  ;;
val get_num : [< `ACC | `ADD | `HALT | `NOP | `POP | `PUSH ] -> int = <fun>

こんなとかかなあ。 そういや 2ch の ML スレでこんな感じのネタが出たことあったっけ? オペコードから数値だけじゃなく、逆向きに数値からオペコードってのも欲しいなら、こんなのも良いかも。

# let op_list =
  [ `NOP,  0;
    `PUSH, 1;
    `POP,  2;
    `ACC,  3;
    `ADD,  4;
    `HALT, 5;
  ];;
val op_list : ([> `ACC | `ADD | `HALT | `NOP | `POP | `PUSH ] * int) list =
  [(`NOP, 0); (`PUSH, 1); (`POP, 2); (`ACC, 3); (`ADD, 4); (`HALT, 5)]

# let num_list =
     let ops, nums = List.split op_list in
     List.combine nums ops;;
val num_list : (int * [> `ACC | `ADD | `HALT | `NOP | `POP | `PUSH ]) list =
  [(0, `NOP); (1, `PUSH); (2, `POP); (3, `ACC); (4, `ADD); (5, `HALT)]

# let get_num op = List.assoc op op_list;;
val get_num : [> `ACC | `ADD | `HALT | `NOP | `POP | `PUSH ] -> int = <fun>

# let get_op num = List.assoc num num_list;;
val get_op : int -> [> `ACC | `ADD | `HALT | `NOP | `POP | `PUSH ] = <fun>

Hashtbl 使うのもアリだと思うけど、こういう静的で要素数が小さなものなら assoc list の方がクールな感じがする。 RISC チップのアセンブラなんかだとオペコードが 100 個以上あったりするんで、それはさすがにハッシュテーブルの方が良さそうな気がするけど。


トップ 最新 追記

日記ってのは本来、自分で読み返すためにあるもんだよなあ……
もしくは有名人になったら死後に本になったりとかか?

RSS はこちら

jijixi at azito.com