トップ 最新 追記

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

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|

2008-02-01 [長年日記]

% [clip][雑談] sm1396650 (チーターマンの人気に便乗する男、スパイダーマン!!)

編集が外道すぎるw

黒歴史スパイダーマン関係は定期的に消えることが多いので、どれが定番なんだかさっぱりわからんのだが、とりあえず今見れるので基本形っぽいのは sm2178392 とかなんだろうか。


2008-02-03 [長年日記]

% [雑談] あしたはスーパーボウルの日

さあ、全国一千万人のフットボールファンが待ちに待った日がやってきましたね。 そんなにいねーよ。

何はともあれ、今年もリアルタイムでテレビ観戦する予定。 どうせ無理に仕事しようとしても身が入るわけないし (駄目人間です)。

% [game] FF12 を延々とやり続ける日々

いったいこれっていつ終わるんだろう……

特別おもしろいってわけでもないんだけど、最近の FF シリーズに感じていたダメ要素があまり感じられないせいで特に嫌気がさすこともなく、ある程度ガンビットの設定をしてしまえば戦闘はほとんどボタン押す必要がなくてだらだらプレイするのに向いているせいもあって、ぼんやり他のこと考えながらも延々とやり続けてたりする。

しかし終わりが見えない。

まあ、モブハントとかサブクエストみたいなのにいちいち手を出してるせいもあるんだけど、ストーリーは結局どう落ち着くんだろうね、これは。 なんかこの調子でいくと、最後は尻切れとんぼになりそうな予感がバリバリするんだが。 というか、尻切れにならないんだとしたら、まだまだ終わりそうになくてむしろ恐ろしいんだが(苦笑

どうでも良いけど、主人公 (ヴァンは主人公なんだよね?) のストーリー的な空気っぷりがいっそ清々しいな。 RPG の主人公としてはかなり斬新じゃないか(苦笑

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

Before...

% jijixi [できすぎのシナリオが完成するのは何となく憎らしいので、個人的にはジャイアンツを応援します(苦笑 9.11 事件があ..]

% harache@MIU [初書き込みです。NFLネタだったのでつい。 リアルタイム観戦いいですねー。 私は朝早く会社に出てBSみるかどうか..]

% jijixi [一年に一回のお祭りなんだから、多少の無理は通してでも見るべきです。とか言ってみる :-) ]


2008-02-04 [長年日記]

% [雑談] スーパーボウル前半終了

今年はネタバレに多少配慮しつつ書く。

ニューヨークはオフェンス陣はパリっとしないが、ディフェンスラインの強さが異常。 ニューイングランドの QB ブレイディはファーストシリーズ以降、ほとんど落ち着いてパスを投げられていない感じ。 つーか、すでに 2 サックか 3 サックくらいされてる。 それ以外にもサックに近い状態でダウンとか、ファンブルとか。 あれじゃ、どんな名 QB でも満足な成績は残せまい。 QB の活躍の裏には常にオフェンスラインの尽力があるわけで。

しかし最近は QB サックというとブリッツをかけたラインバッカーがやるもんだと思ってたけど、NY のディフェンスはそれほどブリッツをかけてはおらず、サックしてるのはもっぱら DL 陣。 なんかラインに限っては、実力差がありすぎるチーム同士の試合を見てるような雰囲気だぞ(苦笑

ともあれ、NY はせっかくディフェンスががんばっても、オフェンスがそれを活かせないんじゃ話にならないので、後半はもう少しがんばってほしいもんだ。

% [雑談] スーパーボウル後半終了

いや〜すごくおもしろかった。 史上稀に見る好試合と言って良いんじゃないか。 もう最後の 1 秒まで目が離せないギリギリの展開。 まあ、実際は決着がついた時点が残り 1 秒だったんだが。

リアルタイムで見れなかった人は、ぜひ結果を知らないまま再放送を楽しんでください。 結果を知らないままってのは無理かもしれないけど(苦笑

% [雑談] ところでジャイアンツの攻撃が始まるときに Guns N' Roses の曲が (イントロだけ) かかってたのは何だったんだろう?

マニングの愛称が easy だか何だからしいから「あれ、この曲って it's so easy だっけ?でもこんなイントロだったかな?」とか思ってたんだが、今調べたら Welcome to the jungle だった。 因果関係がさっぱりわからん(苦笑

や、アルバムだとこの曲の次が it's so easy なんだけど、だから何?って感じだしねえ。

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

Before...

% jijixi [あー(苦笑 でもまー、試合はほんとに歴史に残るほどおもしろかったんで、お楽しみくださいませ。]

% きむら(K) [いや、別に本文に*だけ*書かれていたのならまだいいですよ。 そこ、配信しているのはタイトルだけだから。 が、その..]

% jijixi [全文配信でもタイトルに「ネタバレ注意」とか書いてくれれば、とっさに目を逸らせるんですけどねw]


2008-02-05 [長年日記]

% [clip][雑談][Smalltalk] 最もタフになれる「初心者用言語」は Squeak Smalltalk! (sumim’s smalltalking-to)

このところ色んなところで量産されてるこのシリーズだけど、現時点で最高傑作だと思った。

反面、組み込みクラス数が二千以上、メソッド数が五万弱と尋常じゃないから、スルー力も会得できるよ!

スルー力w

% [clip] 母親があまりにもうざいんでケーキ買って食わしたwwwwwwwww (ベア速)

こういうの大好き。良い 2ch のパターンの一つだよね。

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

% sumim [さすが、お目が高い!w ありがとうございます。>傑作]


2008-02-06 [長年日記]

% [雑談] 初心者用言語うんぬん

なんつーか、きむら(K)さんに催促されるまでもなく OCaml で一発書こうとは思ってたんだけども、目指してたのは正に sumim さんが書いたような「愛のある自虐ネタ」だったので、sumim さんのを見て「これには勝てねえ」とあきらめた次第...orz

ちなみに初心者うんぬんの話にマジレスするなら、「初心者用」というのに求められてる要件ってのは結局よく言われているように「成果がすぐに目に見えるようなもの」なわけで、後々変なクセがつかないようにちゃんとした言語を最初から使わせたいというのであれば、その「ちゃんとした言語」にそういう成果が目に見えやすいような仕掛けをつければ良いんだと思う。

別にゲームが作れるとかそういうんじゃなくて、例えばスタックとか関数呼び出しの状態がグラフィカルに表示されるような仕組みとか、そういうのがあると良いんじゃないかなーとか。 自分が何をやってるか見えるっていうのは結構モチベーションアップに繋がると思うんだよね。 というか、初心者の頃ってどんな言語でも「自分が何をやってるのか、よくわからない」状態だと思うんで、そういうのを視覚的に補佐してやれば随分違うような気がする。

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

% きむら(K) [ま、確かに攻撃力最強でしたねw 後段に関しても確かにそのとおりで、(たしかMatz日記のコメントでも突っ込んでた人..]

% sumim [なんと、とんだことで。 いやいや、まだ間に合いますから、あきらめずに是非 OCaml 版を! こういうのは参加するこ..]

% jijixi [いや〜、sumim さんを引き合いに出したのは口実で、実際は単にネタが思いつかなかっただけっす(苦笑 マジメなネタ..]


2008-02-07 [長年日記]

% [game] FF12 一応終わり

予想通りというかなんというか、イマイチ盛り上りにかけるまま終了。 つーか、話の出来云々は別にして、こんなのこの手の RPG でやるようなシナリオじゃないよなーとか。 最後の方のボス敵が人間ばっかりってどうよ?

そんなこんなで、結局 100 時間近くかかったという。 なんというか、ドラクエ 7 以来の「これ、いつ終わるの?」感バリバリなゲームだったね。 初代グランディアみたいに、いつまでたってもおもしろいゲームだと 100 時間くらいへっちゃらなんだけど、DQ7 とかこれみたいにだんだんダレてくるやつだともう惰性だよ。

でも惰性だとか言いつつも、モブハントがごっそり残ってたりするのが気になりすぎるんで、まだしばらくやるだろうな。 まだ全く探索してないダンジョンとかもあるし。

結局ストーリーは印象薄くて最初の頃何やってたかとか全然憶えてなかったりするけど、たぶんこのゲームはその辺を気にしちゃだめなんだよ。 だだっ広いフィールドやダンジョンをてくてく歩いて旅をするのを楽しむゲームなんだと思う。

ガンビットは思ったほど自由度が高くなくて、あんまり遊べなかった。 もう少しマジメに AI 組ませてくれるようだと良かったのに。 そんな感じで戦闘も結局は単調になりがちで、やっぱり歩くのだけが楽しいゲームなのかもしれない。 まあ、1,980 円の元は十分取れたんで良し。


2008-02-09 [長年日記]

% [雑談] 今日のガンダム OO

グラハムがカッコ良すぎるんだが。つーか、こいつが主人公で良いよ、もう(笑

それにしても、悪ガンダム三機のおかげでようやくおもしろくなってきたね。 中盤のあまりのダルさに見るのやめようかと思ってたんだけど、一気に見る気が増してきた。

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

Before...

% Hash [主役機が強いのか弱いのかわからなくなってきましたね・・・後ほど強い機種出てくるんでしょうけど。]

% jijixi [ヴァーチェとナドレのことを考えれば、他のガンダムも何かしらパワーアップする仕掛けが用意されてるんだろうし、エクシアが..]

% Hash [すんません、ようやく18話を見ました! >ガンダムを倒すためにモビルスーツに乗ります……みたいな陳腐な展開だけ..]


2008-02-11 [長年日記]

% [OCaml][Mac] mmatsuoka さんが復活したので、記念に clib をいじってみる

過去の日記がごっそり消えてるのは残念でなりませんが。

ともあれ、一番新しいのを試す。 clib とは何か?というのは上記ページにも書かれているとおり、

Objective Caml のための c-wrapper もどき。

という代物。

まずはインストール。 README を見ると libffi と libdl と findlib が必要と書いてあるが、Mac OS X (10.4 以降) の場合は libdl に相当するものは最初から入っているので、MacPorts で libffi だけ入れる。 findlib は godi で OCaml 入れてる人なら自動的に入ってるはず。 そうでない人はまあ適当に用意する。

その後、単に make とやると ffi.h が見付からなくてエラーが出るので、

% CPATH=/opt/local/include make

みたいにしてやってユル〜く対処。 とりあえず、これでちゃんとできあがるはずなので (少なくともウチの環境ではうまくいった)、おもむろに試してみる。

% ocaml
        Objective Caml version 3.10.1

# #load "camlp4o.cma";;
        Camlp4 Parsing version 3.10.1

# #load "clibp4.cma";;
# #load "clib.cma";;
# clib_include "/usr/include/fnmatch.h" "libSystem.dylib";;
val a : Clib.t = <abstr>
val __builtin_strcmp : string * string -> int = <fun>
(この後、__builtin_* な関数がズラズラと続くので省略)
val fnmatch : string * string * int -> int = <fun>
# fnmatch ("test.*", "test.c", 0);;
- : int = 0
# fnmatch ("test.*", "main.c", 0);;
- : int = 1

すばらすぃ。 でも、stdio.h を読み込むと、

val printf : string -> int = <fun>

↑ だったりするのは、まあ仕方ないのかな。 可変長引数を型安全にするにはいろいろと面倒があるし、増してやそれを自動でやれなんつーのは欲張りすぎなんだろう。

そういや、SWIG ってその辺どうしてたんだっけなあ? 前に調べたことあるような気がするけど、もう憶えてないや(苦笑

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

% mm [Mac でも動くんですね!びっくりです。 ffi.h は configure が無いとまずいとは思っていました。で..]

% jijixi [どうも〜、お元気そうで何よりでした :-) ポインタの扱いなんかも悩ましい感じしますね。特にポインタを渡して値を詰..]


2008-02-14 [長年日記]

% [雑談] 書くネタが無い

ので、なんとなく、とりとめもない近況 (と言っても大したことやってないが)。

ここ数日、仕事のコード書いて、ゲームやって、寝て…… の繰り返し。

ゲームはいろいろ FF12 と一緒に投げ売り品を大量に買ってきて積んでたのを、ちまちま崩しているところ。 PSU イルミナスの野望、1,480 円とか、グリムグリモア 1,980 円とか、バテンカイトス2 1,980 円とか。 しかし、来週には世界樹の迷宮の新作が出てしまうので、これらが全て消化されるのはいつのことやら。

他には、sumim さんに触発されて Rubinius をいじろうと思ったんだけど、なぜかコンパイルに失敗して挫折… とか。 Actors とかあっておもしろそうなんだけど、コンパイルエラーの原因を調査するほどの元気は無くて放置中。 まあ、それ以外でも Rubinius には前から興味だけはあったので、いずれまた何とかしたいところ。

% [雑談] wget で結果を標準出力に吐く

世界で五位の刺身さんが、

wget を STDOUT に出す方法は man をみてもわからなかった。

[【刺身でぐぐると】刺身☆ブーメランのはてなダイアリー【世界で五位】より引用]

と書いてるので、一応 wget だってそれくらいへっちゃらよ、という感じで。(どんな感じだ?)

man wget の -O オプション (--output-document=) のところに、

If - is used as file, documents will be printed to standard output, disabling link conversion.

と書いてあります。 要するに -O - というオプションを付けてやれば標準出力に吐いてくれるということ。

% wget -q http://www.google.com/ -O - | head -c 12
<html><head>
本日のツッコミ(全2件) [ツッコミを入れる]

% きむら(K) [手取り足取りOCaml教えてください>書くネタ とかとりあえずおねだりしてみるテスト ]

% jijixi [身体で憶えるタイプだから人に教えるのとか苦手なんすよね(苦笑 「あーなって、こーなって、そーなるんだよ」みたいな。..]


2008-02-15 [長年日記]

% [OCaml] 猫にもわかる OCaml 入門、その 1

すいません、猫にはわかりませんでした。 予定を変更して『猫にはわからない OCaml 入門』をお送りします。

このコーナー(?)は、なんとなく OCaml がわかったような気になるのを目指してぐだぐだな感じで進めていくものです。 ちゃんと OCaml に入門したい人は、『Objective Caml 入門』とかを読みましょう。

なんとなくわかれば良いので、正式な用語とか意味とかはぶっちぎります。 このページで使われている用語、呼称などは絶対に鵜呑みにせず、ちゃんと自分で正しい言葉を調べて憶えましょう。 うっかりそのまま口走って周りから白い目で見られても当方は関知いたしません。

OCaml とは何ですか?
『関数型言語』とカテゴライズされる種類のプログラミング言語です。フランスの『うりゃ〜』だか『いりゃ〜』だかそんな感じの大学だか研究所だかよくわからないところで作られました。
関数型言語とは何ですか?
人によって解釈が大きく異なるため、しばしば宗教戦争を引き起こす魔の言葉です。安易に使ってはいけません。だいたいは『関数が第一級の値 (first class value)』で『関数的プログラミングを助けるような機能が多く用意されている』言語くらいの意味で捉えておけば良いでしょう。でもその解釈を誰かに押しつけようとするとトラブルに巻き込まれる可能性があるので気をつけてください。
第一級の値とは何ですか?
その言語における一番基本的な型の値 (C なら int とか) と全く同じように扱えるようになっている値のことです。
関数的プログラミングとは何ですか?
数学における関数のように、同じ入力には必ず同じ出力が返るような構成でプログラミングを行なう手法です。そうすることでプログラマが問題を切り分けやすくなるために、バグが混入しにくくなるとか言われていますが、事実のほどは定かではありません。基本的には副作用が無いように書いていけば、とりあえず関数的になります。
副作用とは何ですか?
関数に与える値 (引数) と返ってくる値 (返り値、戻り値) 以外のところに現われる何かです。例えばコンソールへの文字の表示などがよくある例になります。ハスなんとかいう言語では、この副作用を『見なかったこと』にすることで純粋に関数的だなどと言いはっていますが、OCaml では見ないふりはせず普通に副作用を扱います。そのことにより、『非純粋関数型言語』と呼ばれることもあります。ちなみに、どこぞの何だか綺麗っぽい言語では、副作用を見なかったことにするのではなく、一回しか見ないと決めることで純粋さを保っています。たしかに一回しか見なければ、起こる現象は常に同じです。だって一回しか見ないんですから違いを比べるものがありません。なんだかヘリクツくさいですが、見なかったことにするよりは潔い気もします。
っていうか、いつになったら OCaml に入門できますか?
正直自分でもそろそろ疲れてきたので、本題に入りたいと思っていました。

OCaml の特徴

  • 厳格で静的な型付け
    • 暗黙の型変換 (キャスト) は諸悪の根源なので絶対に許しません。
    • 静的に型付けされるため、コンパイルされた時点で「思ってもみない型の値が関数に渡されてぬるぽ」のような切ない現象は起きません。
  • でも型推論のおかげで型情報などを自分で書く必要は少ない
    • C/C++/Java プログラマが OCaml でコードを書くと涙を流すそうです。(脳内ソースからの情報)
  • パターンマッチ
    • 正規表現のことはとりあえず忘れてください。
    • 一度ハマるとやめられない魅力があります。
  • C 系の言語から見るとクセのある文法
    • 文法がキモいとか言って渋るような人は、新しい言語を学ぶ資格がありません。
    • 大丈夫、なにごとも慣れですよ、慣れ。

まだまだありますが、とりあえずはこのくらいで。 あまり長々と書いても読む方が疲れるでしょうから。 というか、書く方が疲れます。もうめんどくさいです。

もしも次回があれば、基本型の説明なんかをするかもしれません。

% [雑談][Mac][zsh] 本題とは全然関係無いが……

odz さんとこのエントリを見て、「うわ、何これ怖っ」とか思いつつ、それはそれとして stat ってコマンド使ったこと無い気がするなと思って手元でも試してみたんだが……

% stat MacVim-snapshot-22.tbz
device  234881033
inode   186538
mode    33188
nlink   1
uid     501
gid     80
rdev    0
size    7812907
atime   1203050525
mtime   1203050481
ctime   1203050510
blksize 4096
blocks  15264
link    

あれ?全然出力違うじゃん。なんじゃこりゃ?と思ったら、実は zsh には組み込みで stat というコマンドがあったという事実。

% where stat
stat: shell built-in command
/usr/bin/stat
% /usr/bin/stat MacVim-snapshot-22.tbz
234881033 186538 -rw-r--r-- 1 jijixi admin 0 7812907 "Feb 15 13:42:05 2008"
"Feb 15 13:41:21 2008" "Feb 15 13:41:50 2008" "Feb 15 13:41:06 2008" 4096 15264 0
MacVim-snapshot-22.tbz

や、それだけ。

% [雑談][Ruby] 常に同じ階層のモジュールだけ探索してほしいとき

どうしたら良いかというのが、名前空間の分離が気になりすぎて夜も眠れない人間にとっての懸案事項だったりする。

irb(main):001:0> module A
irb(main):002:1>  def self.f; p 'A' end
irb(main):003:1> end
=> nil
irb(main):004:0> module B
irb(main):005:1>  module A
irb(main):006:2>   def self.f; p 'B::A' end
irb(main):007:2>  end
irb(main):008:1>  def self.f; A.f end
irb(main):009:1> end
=> nil
irb(main):010:0> module C
irb(main):011:1>  def self.f; A.f end
irb(main):012:1> end
=> nil
irb(main):013:0> A.f
"A"
=> nil
irb(main):014:0> B.f
"B::A"
=> nil
irb(main):015:0> C.f
"A"
=> nil

通常、こう↑ いった感じで、まず同じ階層に該当する名前があるか見て、無ければルートから探すようになっていて、それはそれで便利なんだけど、

irb(main):016:0> module Foo
irb(main):017:1>  def self.f; p 'Foo' end
irb(main):018:1> end
=> nil
irb(main):019:0> module Bar
irb(main):020:1>  module Foe
irb(main):021:2>   def self.f; p 'Foe' end
irb(main):022:2>  end
irb(main):023:1>  module Baz
irb(main):024:2>   def self.f; Foo.f end
irb(main):025:2>  end
irb(main):026:1> end
=> nil
irb(main):027:0> Bar::Baz.f
"Foo"
=> nil

例えばこんな↑ とき。 ほんとは Baz.f の中身は Foe.f と書きたかったんだけど、ついタイポっちゃって、しかもたまたまトップレベルにタイポったのと同じ名前のモジュールが存在して、同じ名前のメソッドを持ってたりすると、なんだかよくわからないエラーに悩まされることになったりする。

で、こういうときには、Baz.f での Foe に対する参照を間違いなく同じ階層のものを見にいくように指定したいわけだ。 タイポってたんならそこでエラーになって欲しいわけ。 要するにファイル名で言うところの './hoge' みたいな指定をしたい。

したいんだけど、どうも上手い方法が思い付かないんだよな。 まあ上記の例に限れば (モジュールメソッドの定義内であれば)、

irb(main):028:0> module Bar
irb(main):029:1>  module Baz
irb(main):030:2>   def self.f; self::Foo.f end
irb(main):031:2>  end
irb(main):032:1> end
=> nil
irb(main):033:0> Bar::Baz.f
NameError: uninitialized constant Bar::Baz::Foo
 from (irb):30:in `f'
 from (irb):33

こんな感じで行けなくもないんだけど、Mix-in のためのモジュールでインスタンスメソッドを定義してる場合にはそうも行かない。 結局、

irb(main):034:0> module Bar
irb(main):035:1>  module Baz
irb(main):036:2>   def f; ::Bar::Baz::Foo.f end
irb(main):037:2>  end
irb(main):038:1> end
=> nil
irb(main):039:0> class Hoge
irb(main):040:1>  include Bar::Baz
irb(main):041:1> end
=> Hoge
irb(main):042:0> Hoge.new.f
NameError: uninitialized constant Bar::Baz::Foo
 from (irb):36:in `f'
 from (irb):42

こんな風に完全な名前を指定してやるような形しか思い付かないんだが、どうも納得行かないというかねぇ。 やたら長いし。 なんか良い方法知ってる人、教えてください。

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

% drkazu [>大丈夫、なにごとも慣れですよ、慣れ。 結局、ここに帰着する気がしましたw]

% jijixi [人間は順応性が高い動物ですからw 実際私も最初に OCaml をいじり始めたときは「何これキモすぎる」とか思ってま..]


2008-02-17 [長年日記]

% [OCaml] 猫にもわかるかもしれない OCaml 入門、その 2

がっ。誰もしてくれなかったので、自分でしときました。

そんなわけで、おそらく猫にはわからないですが、一応わかるようにがんばってみようとする OCaml 入門第二回です。 特に思い付かなかったので、予定どおり基本的な型について説明しましょう。

OCaml は長い呼び名では Objective Caml と言い、その名から察っせられるようにオブジェクト指向プログラミングのための機能を持っていますが、全てがオブジェクトというわけではなく「unboxed な」とか「primitive な」などと言われる型の値を持っています。 と言うよりオブジェクトに関しては完全にオプショナルであり、必要が無いなら全く使う必要はありません。

さて、それでは対話環境を起動してください。 え?まだインストールしてないって?インストールしてください。 え?インストールの仕方を教えろ?

ググれ。

…… さて、用意できましたか。 コマンドプロンプトで ocaml と入力すれば対話環境が動きます。 ledit とか rlwrap を用意できるなら一緒にあると幸せになれます。

OCaml のプロンプトは # です。 なんだか偉そうですね。 ともあれ何か打ちこんでみましょう。

# 1;;
- : int = 1

セミコロン二つは「ここまでで一区切りですよ」と対話環境に教えるためのおまじないです。 ファイルにソースコードを書く場合に必要になることはあまりありませんが、エディタの整形支援が効きやすくなったりという場合もあるようで、敢えて書くようにしている人もいるようです。 ちなみに私は書きません。キモいので。 あと、セミコロンが一つだと「ちょっと区切るけど、まだ続くよ」という意味になります。 こちらは普通に使います。と言うか使わないと色々困ります。

そんなところで本題に入っていきましょう。 先程打ち込んだ例ですが、

- : int = 1

この部分は対話環境が返してきた結果です。 1;; という入力は対話環境に「1 を計算しなさい」と指示していることになります。 もちろん、どう計算しようが 1 は 1 なので結果は 1 です。 結果の表示は int という型の 1 という値を示しています。 行頭の - は名前が無い場合に使われる仮の名前で : は名前と型の区切りです。 とりあえず、今は気にしなくて大丈夫。

さて、それでは OCaml にはどんな型が用意されているのか見ていきましょう。

整数型 int

32bit アーキテクチャでは 31bit、64bit アーキテクチャでは 63bit の範囲を持つ符合付きの整数です。 なぜ 1bit 足りないのかについては諸説ありますが、一般的にはラムダの神様に捧げられているのだと言われています。

OCaml においては int は常に int です。 プログラマが敢えて変換しないかぎり、決して別の型に変わることはありません。 もちろん最大値や最小値を越えて値がオーバーフローしても別の型になることはないので、その計算はグダグダになります。 注意しましょう。

その他の整数型 int32 int64 nativeint

それぞれ int32 は 32bit、int64 は 64bit、nativeint はアーキテクチャネイティブの範囲を持つ整数です。 ラムダの神様への捧げ物をケチった結果、int に比べると効率がよろしくありません。 どうしても 1bit が惜しい場合や、ぴったり 32bit/64bit な値が欲しい場合などにしか使う意味は無いでしょう。 単に int の範囲を越えた整数を使いたい場合には、Num モジュールを使う方が自然です。

浮動小数点小数型 float

倍精度の浮動小数点数です。 この型の値を書きたい場合は必ず小数点を付けます。

# 1.0;;
- : float = 1.
# 1.;;
- : float = 1.

小数点が付いていない数字は常に整数です。 OCaml は文脈とか空気とか読みません。 1 と書いたらそれは常に整数の 1 であり、1.0 と書いたらそれは常に小数の 1.0 なのです。 そして、これらをきちんと型の変換をせずに混ぜて計算することはできません。

# 1 + 1.0;;
This expression has type float but is here used with type int

エラーの意味はここでは気にすることはありません。 混ぜて計算することができないとだけ理解してください。 それどころか同じ足し算でも整数と小数では演算子が違います (小数の足し算には +. を使います)。 つまり、整数として計算しているのか、小数として計算しているのかをプログラマははっきりと目に見える形で指定することができるということです。

え?それってめんどくさくないのかって? もちろんめんどくさいです。 でも、C 言語のような整数と小数の扱いが曖昧な言語で、その曖昧さが引き起こすトラブルに悩まされた経験のある人には、こういう厳密さの必要性もわかってもらえるのではないでしょうか。 少なくとも私は好きです。 めんどくさいですけど。

文字型 char

1 byte 範囲の文字です。 文字ったら文字なんです。 事実上 int と可換ですが、それでもちゃんと変換しないと整数として扱ったりはできません。

# 'a';;
- : char = 'a'

文字列型 string

文字列です。 だいたいは char の配列みたいなものです。 char は 1byte 範囲ですから、マルチバイト文字などが考慮されたりはしません。

# "hoge";;
- : string = "hoge"

真偽値型 bool

true か false です。 それ以外ありません。 0 が偽だとか空リストが偽だとか、そういった事実は一切ありません。

# true;;
- : bool = true
# false;;
- : bool = false

例のアレ unit

値の無い値です。() と書きます。 返すべき値が無い関数はこれを返します。

# ();;
- : unit = ()

例外型 exn

各種プログラミング言語で言うところの例外です。

タプル型 tuple

厳密には tuple という型は存在しません。 複数の型によって作られる複合型の総称が tuple です。 例えば int と string の組み合わせなら int * string という型になります。

# (1, "foo");;
- : int * string = (1, "foo")

タプルは順番や数など組み合わせによって無限の数存在し得ます。 順番も関係するので int * string と string * int は違う型です。

配列型 'a array

固定長配列です。 'a というのは配列の要素の型を示すものです。 ダッシュ記号で始まる型名は型変数と呼ばれるもので、どんな型でも入り得ることを表わします。 と言っても一つの配列の中に複数の型が混在できるということではありません。 一つの配列に入れられるのは、一つの型の値だけです。 例えば int の値を入れたなら、その配列の型は int array となります。

# [||];;
- : 'a array = [||]
# [|1;2;3|];;
- : int array = [|1; 2; 3|]

各値の区切りにはセミコロン(;)を使います。 カンマ(,)を使うと違う意味 (上記の例で言えば、int * int * int というタプルの配列) になってしまうので気を付けましょう。

リスト型 'a list

広義の関数型言語にはほぼ必ず存在する型で、いわゆる連結リストです。 関数型と連結リストに何の関係があるかと言うと、関数的なプログラミングをしたい場合に便利なのです。 配列は中身を逐次書き換えていくような処理の仕方に適していますが、リストは中身を書き換えるのではなく、どんどん新しい値を作っていくような処理の仕方に適しています。

リストの扱いは関数型言語のキモと言っても良い部分なので、いずれみっちりやります。たぶん。 今のところはリストとは『先頭の値』と『残りの部分のリスト』の組でできているものとだけ憶えておきましょう。 実際、'a list は再帰的な定義により、

'a list = [] | 'a * 'a list

と表わされます。 ここで [] は空リストです。| は or の意味なので、'a list は空リストもしくは 'a と 'a list のタプルであると定義されるということです。 OCaml では 'a * 'a list という型の値を作るために :: という記号を使用します。

# 1 :: [];;
- : int list = [1]
# 1 :: [2;3];;
- : int list = [1; 2; 3]
# [1;2;3];;
- : int list = [1; 2; 3]

リストについても配列と同様、区切りはセミコロンです。

オプション型 'a option

OCaml には基本的には NULL とか nil とかそういう値がありません。 ある関数の引数が int と型付けされていれば、そこには int しか来ないのです。 ぬるぽは理論上存在しないのです。がっ。

でも時にはそういったものが必要な場合もありますよね? 例えばファイルを読み込んで文字列を返す関数があったとして、読み込みに失敗して返すべき文字列が存在しない場合など。 そういった場合、このオプション型を使うことで値がある場合と無い場合をひとまとめにして扱うことができます。 値が無い場合は None を、値がある場合は Some を使います。

# None;;
- : 'a option = None
# Some 1;;
- : int option = Some 1

OCaml に組み込まれた基本型は以上です。 実際にはさらに format4 と lazy_t というのがありますが、どちらも特定のモジュールのためだけに存在するようなものなので、今回は省きます。 いずれ機会があれば紹介しましょう。

実のところ OCaml の型システムはここからが本番です。 これら基本型を組み合わせて様々な型を作っていくのが醍醐味になります。 そのための仕組みの一つがすでに紹介したタプルです。 他にもレコード、ヴァリアント、オブジェクトなどがありますが、それらはまた次回以降紹介していきたいと思います。

今回はネタを仕込むところが少なくて、まじめなことばっかり書いたので疲れました。 次は何をやったら良いんだろう。

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

% たぶん猫以下のきむら(K) [すみません。土曜日分で反応しようと思っていたのですが 忘れてしまいました。]


2008-02-18 [長年日記]

% [雑談] 何の気無しにクアーズオリジナル (というビール) を買ってきたら原産国が中国になってて絶望した

クアーズってカナダかどっかの会社のはずなんだがなー……

まあ、今のところ中国産ビールで当たったとかいう話は聞いたことないんで大丈夫だとは思うが(苦笑

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

% Hash [確かアメリカだった気がします。だ、ダイジョウブですよきっと!]

% jijixi [まあ、気付いたのがたまたま今回だっただけで、クアーズを飲むのは初めてだったわけじゃないんで、何かあってももう手遅れか..]

% drkazu [ショックが大きいですなーーーw 既に流通が地球規模になって、産地の限定が難しくなってきたんですかね〜]


2008-02-19 [長年日記]

% [OCaml] 猫もいつかはわかってくれる OCaml 入門、その 3

わかってくれるかもしれません。 …… たぶん無理。

さて、三回目の今回は変数と関数について説明したいと思います。 これを読んでいるみなさんが、これまでどのような言語を経験しているかわかりませんが、いわゆる関数型言語というものにあまり馴染みが無い場合、OCaml の変数はちょっと奇妙なものに見えるかもしれません。 何が奇妙なのかと言うと、『代入』ができないのです。 代入できない、つまり値が変更できないくせに『変数』という名前なのはどうかと思いますが、ともあれできません。 代わりに『束縛』という操作ができます。 束縛には let という構文を使います。

# let hoge = 1;;
val hoge : int = 1

これは hoge という名前の変数に 1 という値を束縛したところです。 これで hoge と書けばそれは 1 のことになったので、次のように書くと……

# let fuga = hoge;;
val fuga : int = 1

fuga も 1 になります。 簡単ですね。 でももう hoge の値を変えることはできません。 代入できませんから。

# let hoge = 2;;
val hoge : int = 2

できるじゃねーか!!

……って、ちょっと待ってください。 これはいかにも hoge に 2 を代入したように見えますが、実際は微妙に違います。 それを説明する前に、ここでちょっと浮気して Ruby を使ってみましょう。 Ruby は知ってますよね?日本人なら当然です。そう、あの赤い宝石のことです。 同じ石でも青いものは Sapphire と呼ばれます。 高い硬度と摩耗しにくい性質から、小型精密機械などの部品として欠かせない存在です。 ……すいませんスベりました。 とにかく、Ruby を使ってみます。 Ruby は代入ができる言語です。

irb#1(main):001:0> hoge = 1
=> 1

irb#1(main):002:0> fuga = Proc.new { p hoge }
=> #<Proc:0x00391d04@(irb#1):2>

irb#1(main):003:0> fuga.call
1
=> nil

hoge という変数に 1 を代入し、fuga という変数には hoge の中身を表示させる手続きを代入しました。 その手続きを実行すれば、当然 hoge の中身である 1 が出力されます。 では、同じことを OCaml で書いてみましょう。

# let hoge = 1;;
val hoge : int = 1

# let fuga = fun () -> print_int hoge; print_newline ();;
val fuga : unit -> unit = <fun>

# fuga ();;
1
- : unit = ()

fun から続く部分は関数型の値です。 関数型については後で説明しますが、とりあえずこの例は、ユニット型の値を引数に取り、hoge の値を表示し、次に改行を表示する関数を意味しています。 それを fuga に束縛しているわけですね。 そして fuga () でその関数を実行です。 もちろん hoge の中身は 1 ですから 1 が出力されていますね。 ここまでは Ruby と同じです。

では次に Ruby で以下のようにしてみましょう。

irb#1(main):004:0> hoge = 2
=> 2

hoge に 2 を代入しています。 さて、ここで fuga.call を実行すると何が出力されるでしょうか?

irb#1(main):005:0> fuga.call
2
=> nil

2 が出力されました。 hoge に 2 を代入したことにより、表示される値も変化したわけです。 OCaml ではどうでしょう?

# let hoge = 2;;
val hoge : int = 2

# fuga ();;
1
- : unit = ()

2 ではなく 1 が表示されましたね。 これはどういうことかと言うと、要するに hoge の値は変わってはいないということです。 意味がわかりませんか? fuga という関数を定義した時点の hoge は今新たに定義した 2 という値を持つ hoge とは別の存在なのです。 単に以前の定義が新しい定義によって覆い隠されて見えなくなっただけで、fuga が見ていた hoge は依然として 1 のままであり続けています。

この事実は何をもたらすでしょうか。 一言で言えば「関数的プログラミングがやりやすくなる」です。 fuga を定義した時点でこれ以降 fuga () の結果はずっと変わりません。 プログラマは「どこかで hoge の値が変更されたらどうしよう」などと悩む必要が無くなります。 もちろん fuga を新たに定義すれば違う挙動をする fuga を作れますが、それ以前に誰かが見ていた fuga はやはりそのまま最初の hoge を表示する fuga のままであって、「後から」以前の定義に何か影響を及ぼすことはあり得ません。

OCaml における変数の挙動はなんとなくわかってもらえたでしょうか。 OCaml は関数型言語ですから関数的プログラミングがやりやすいようにできています。 以前、副作用とは関数の引数と返り値以外のところに現われる何かだと説明しましたが、それは文字の表示などのように「どこかに影響を及ぼす」ものだけではありません。 上記の Ruby の例のような「どこかから影響を及ぼされる」ものもやはり副作用です。 OCaml はそういうことが起こりにくいように作られています。

さあ、それでは let の使い方を憶えたところで関数について説明していきましょう。 OCaml では関数は第一級の値です。 つまり前回紹介した基本型などと全く同様に扱うことができます。 要するに、関数を定義するということは、関数の実体 (関数型の値) を作りそれを変数に束縛するということです。

関数型の値を作るには、先程の例のように fun という構文を使います。 例えばある整数を二倍にして返す関数は以下のように書きます。 x がいわゆる仮引数です。 もちろん x じゃなく好きな名前を付けてかまいませんが、関数型言語の例ではこういう何でも良い値には x, y, z 辺りを使う傾向が強いようです。 関数型言語は数学と仲良しっぽいからのようですが、数学とちっとも仲が良くなかった私は最初なかなか馴染めませんでした。 でも、きっとどこに行ってもこういう表記になっていると思うので、がまんして慣れてください。

# fun x -> x * 2;;
- : int -> int = <fun>

int -> int というのがこの関数の型です。int 型の値を与えると int 型の値を返すという意味になります。 実際にはこれだけだと後で使うことができないので、let を使って名前を付けます。

# let double = fun x -> x * 2;;
val double : int -> int = <fun>

# double 2;;
- : int = 4

OCaml における関数は常に 1 つの引数を取って、1 つの値を返します。 では x を n 倍する関数、つまり引数が複数必要になる関数が書きたくなったらどうすれば良いでしょうか? 一つの答えとしては引数にタプルを使います。 つまり以下のようなことです。

# let times = fun (x, n) -> x * n;;
val times : int * int -> int = <fun>

# times (2, 3);;
- : int = 6

int * int 型の引数を取って、int 型の値を返す関数ができました。 これはこれで良いのですが、もっと他に方法は無いでしょうか? OCaml では関数も通常の値と同じ扱いだということを思い出しましょう。 それを利用することで以下のような書き方ができます。

# let times = fun x -> (fun n -> x * n);;
val times : int -> int -> int = <fun>

int 型の値を受けて、int -> int 型の値を返す関数ができました。

# times 2;;
- : int -> int = <fun>

# times 2 3;;
- : int = 6

タプルを使うよりもすっきりしていますね。 OCaml に付属している標準ライブラリの関数は、通常こちらの形で作られています。 ちなみに OCaml の親戚である Standard ML では逆にタプルを使った形で標準ライブラリが整備されています。

さて、とは言え引数の数が増えるごとに fun と書く数が増えていくのもおもしろくありません。 なので、実際には同じ効果を持つ簡略記法が存在します。 上記の例は以下のように書けます。

# let times = fun x n -> x * n;;
val times : int -> int -> int = <fun>

# times 2 3;;
- : int = 6

いくらかすっきりしましたね。 でも、そろそろ fun と書くのも飽きてきました。 省略しましょう。

# let times x n = x * n;;
val times : int -> int -> int = <fun>

# times 2 3;;
- : int = 6

ここまで来れば他の言語の関数定義と大差ありません。 カッコやカンマが必要無い分、こちらの方がすっきりしているとさえ言えそうです。

ところで、この例のような「一つの引数に一つの返り値」にバラすことができる構成の関数を「カリー化された関数」と呼びます。 これは、インド人が食事の際に右手のみを使うことから来た呼び名だと言われています。

最後にローカル変数についても説明しておきましょう。 外の世界の名前空間を汚さないようにするのはプログラマの嗜みです。 ローカル変数の定義には let in 構文を使います。

# let foo = 20 in print_int foo; print_newline ();;
20
- : unit = ()

# foo;;
Unbound value foo

foo という変数は in に続く一連の式においてのみ有効です。 よって、その外の世界には foo という変数は (まだ定義されていないので) 存在しません。 もちろん、通常の let と同じように関数の定義もできます。 当然その関数は in に続く式でだけ有効なものです。

今回はこんなところでしょうか。 次回は副作用と仲良くする方法を説明する予定です。

……あと、カリー化の話は信じないように。(そんな人いないと思いますが)


2008-02-20 [長年日記]

% [Scala] Java 互換になった Generics を試す

たしか 2.6.? あたりからオプショナルに導入されていた Java 互換の Generics が、2.7.0 からはデフォルトになるということで、ちょっくら試してみたりとか。

Welcome to Scala version 2.7.0-RC2 (Java HotSpot(TM) Client VM, Java 1.5.0_13).

scala> val a = new java.util.ArrayList[(Int, String)]
a: java.util.ArrayList[(Int, String)] = []

scala> a.add((5, "hoge"))
res0: Boolean = true

scala> a
res1: java.util.ArrayList[(Int, String)] = [(5,hoge)]

scala> a.add(("fuga", 4))
<console>:6: error: type mismatch;
 found   : java.lang.String("fuga")
 required: Int
       a.add(("fuga", 4))
              ^

おー、パチパチパチ。 これでますます Java との相互運用性が高まったねえ。

まあ、これまでも ArrayList とかこの辺のコレクションクラスは scala.collection.jcl パッケージにラッパークラスが用意されていたので、それらに関してはそれほど不便は無かったんじゃないかという気はするけど (実際は知らん)、あらかじめラッパーが用意されていなくても Java のクラスで Generics が使えるというのは Java の資産をいただいてしまおうという目論見の際には便利に働くことだろう。

% [Scala] Java 互換の Generics 続き

相互運用性を云々するなら、Java 側に存在する Generics を使った値を普通に扱えることも示す必要があるかな。

% cat Test.java
import java.util.ArrayList;
public class Test {
   static ArrayList<String> al = new ArrayList<String>();
}
% javac Test.java
% ls
Test.class Test.java
% scala -classpath .
scala> Test.al
res0: java.util.ArrayList[java.lang.String] = []

scala> Test.al.add("hoge")
res1: Boolean = true

scala> Test.al
res2: java.util.ArrayList[java.lang.String] = [hoge]

scala> Test.al.add(1)
<console>:5: error: type mismatch;
 found   : Int(1)
 required: java.lang.String
       Test.al.add(1)
                   ^

うむ、大丈夫。

% [Scala] Stream#take の問題はいつの間にか解決されていた模様

ふと思い付いたので、以前の Stream#take の実装がまずい問題がその後どうなったかなーと試してみたが、ちゃんと対処されたようだ。

Welcome to Scala version 2.7.0-RC2 (Java HotSpot(TM) Client VM, Java 1.5.0_13).

scala> val s = Stream.from(0)
s: Stream[Int] = Stream(0, ?)

scala> val part = s.take(10)
part: Stream[Int] = Stream(0, ?)

scala> part.length
res0: Int = 10

scala> val s = Stream.range(0,5).take(10)
s: Stream[Int] = Stream(0, ?)

scala> s.length
res1: Int = 5

これで安心して Stream を使えるね。

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

% keisuken [scala.collection.jcl._で困る事は,MapやListそのものをラッピングできないことでしょうか...]

% jijixi [なるほど、実際に使ってる人の意見は参考になります。 ともあれ、 Java 互換になったことの恩恵は結構大きそうです..]


2008-02-21 [長年日記]

% [OCaml] 猫だってわかりたい OCaml 入門、その 4

わかりたいと思ってるよ、きっと。可能性は 0 に近いけど。

前回の変数の説明を読んで絶望した人も多いでしょう。 「代入ができないって、じゃあどうやってループ書くんだよ!!」という声が聴こえるようです。 でも安心してください、そんなあなたのために実はこっそり抜け道が用意されているのです。

と言うわけで、今回は予告どおり副作用と仲良くなります。 ここで言う『副作用』は主に『破壊的な変更』を指します。 要するに代入のことです。

関数的プログラミングとは、基本的には副作用を排除することで実現されます。 ですが、例えそれが理想であっても、現在のコンピュータは関数的プログラミングに最適化されているとは言えません。 クイックソートは配列を破壊的に書き換えてこそクイックで空間効率も良いのです。 ハスなんとかの話でよく引き合いに出される例なんかに騙されてはいけません。

もちろん、OCaml は関数型言語ですから、プログラムを書く際にはなるべく関数的であるよう努力すべきです。 そして、そのようにした方が幸せになれるはずなんです。 でも、だからと言って、副作用を必要以上に避ける必要はありません。

良いですか? 例えば 1 と入力すれば必ず 2 を返す関数があったとします。 その関数は『関数的』でしょうか? もちろん関数的だと言えます。 でも、実はその関数は内部においてはガンガン破壊的な変更を行なっていたのです。 ただしそれは内部だけに閉じていて、関数の外には何ら影響を及ぼしません。 それで、結局この関数は『関数的』だと言えるでしょうか?

ここで『言えない』と答えるような人は、とっととハスなんとかや清潔な言語の方へ行っちゃってください。 あなたに OCaml は向いていません。 『言える』と答えた人はこれからもよろしく。

良いですか? きちんと自分の手に負えるような、ごく狭い範囲に閉じた状態で使う副作用は、もう副作用ではありません。 それは単なる実装方法の一つにすぎないのです。 外の世界に影響を及ぼさなければ、好きなように副作用を使っても良いのです。 OCaml は『関数型言語』ですが、副作用を否定しません。 使いたいなら使えば良いのです。 その気になれば、いわゆる手続き型言語のようなコードだって書けます。

そんなところで、そろそろ本題に入りましょう。 OCaml において破壊的な変更が可能な値としては、主に以下のようなものがあります。

  • 配列
  • 文字列
  • リファレンス

実際には他にもありますが、説明がめんどうなので今は省きます。

さて、配列や文字列はすでに紹介しましたが、ここでいきなり出てきたリファレンスとは何物でしょうか。 これは簡単に言うと何らかの値を入れておくための箱です。 長さが 1 の配列のようなものと思えば良いと思います。 文字列は配列の仲間のようなものですから、話を配列に絞りましょう。

配列とは要するに値を入れておくための箱が並んでいるようなものです。 その並んだ箱を変数に束縛した場合、前回説明したようにその箱はずっと不変です。 ですが、不変なのは箱だけです。箱の中身は変えられます。

# let ary = [|1; 2; 3|];;
val ary : int array = [|1; 2; 3|]
# ary.(0) <- 5;;
- : unit = ()
# ary;;
- : int array = [|5; 2; 3|]

ary.(添字) という表記は添字 (インデックス。0 から始まります) の位置の値にアクセスするための構文です。 そこに代入のための <- という記号を使い値を入れます。 そうすることで、ary という箱自体は同じなまま、その中身だけ変化しているのです。 ちなみに文字列に対して添字によるアクセスをするには丸カッコではなく角カッコを使います。

# let str = "hoge";;
val str : string = "hoge"
# str.[1] <- 'a';;
- : unit = ()
# str;;
- : string = "hage"

これは整数と小数の演算子が違うように、何に対してアクセスしているのか字面によってはっきりさせるための仕様です。 角カッコを使っていれば、それは間違いなく文字列に対してそうしているのだとすぐにわかります。

リファレンスだけはちょっと勝手が違い、代入にも専用の記号が使われます。 リファレンス型の値を作るには ref という構文を使います。

# let r = ref 1;;
val r : int ref = {contents = 1}

int ref というのが型名です (contents 云々は今は気にしないでおいてください。いずれわかります)。 int と付いているのでわかるかもしれませんが、このリファレンス型の値には int 型の値しか代入できません。 これは最初に 1 という int 型の値を入れたからで、例えば string 型の値を入れたのであれば型は string ref となり string 型しか代入できない値になります。

# let s = ref "foo";;
val s : string ref = {contents = "foo"}

先程述べたとおり、リファレンスは箱のようなものです。 ここで変数に束縛されているのはあくまでもその『箱』そのもので、中身の値を取り出すには配列における添字アクセスのように取り出すための操作をしなくてはいけません。 そのために用意されている記号は ! です。

# !r;;
- : int = 1

このように、! を前に置くことでリファレンスの中身が取り出せます。 言語によっては ! 記号は真偽値の否定を表わすことがありますが、OCaml では全く関係ありません。 気持ちが悪いかもしれませんが慣れましょう。

代入には := を使います。

# r := 2;;
- : unit = ()
# !r;;
- : int = 2

多少面倒ではありますが、リファレンスを使うことで代入可能な変数 (の代用品) が手に入りました。 ではみなさんお待ちかねのループを書きましょう。 OCaml には while と for の二種類のループ構文が用意されています。

# let i = ref 0;;
val i : int ref = {contents = 0}
# while !i < 3 do
    print_int !i;
    print_newline ();
    incr i
  done;;
0
1
2
- : unit = ()
# for j = 0 to 2 do
    print_int j;
    print_newline ()
  done;;
0
1
2
- : unit = ()

このようになります。 while の例で使っている incr という関数は int ref 型の値を与えると、その中身の値に 1 を足して代入しなおします。 要するにインクリメントしてくれる関数です。 デクリメントのための decr という関数もあります。 説明不要だと思いますが、while は !i < 3 という条件が満たされているかぎりループを続けます。

for の例の 0 to 2 は結果からもわかるように 0 から 2 まで値をインクリメントして j に束縛しループを回します。 to の代わりに downto を使うとデクリメントになります。

それではここで質問タイム。

他の言語で言うところの continue とか next のようなものは無いんですか?
ありません。
他の(略)の break とかは無いんですか?
ありません。
for ループでカウンタの値を 2 ずつ進めたいんですが?
できません。

………不便じゃね?

そうです、不便です。 これぞ OCaml の巧妙な罠。 実は OCaml でループを書きたいときは普通 while やら for なんて使わないのです。 もちろん使っても良いんですよ。使うことは否定しません。不便ですけどね。フヒヒ。 あえて中途半端なループ構文を用意することで、最初に喜ばせておいて後で叩き落とし、推奨するやり方に誘導するとは OCaml ったら怖い子。

まあ、continue や break の問題は例外 (いずれ説明することもあるでしょう) を利用することでごまかせますし、カウンタの話は while を使うなり二倍するなり工夫すれば可能なんですが、無理にそんなことするくらいなら推奨される方法を試してみるのも良いじゃないですか。 そちらで挫折したら、またこっちの世界に戻ってくれば良いんです。

といったところで今回はおしまいです。 次回は関数的なループに挑戦します。 要するに『再帰』です。

% [雑談][game] あー、そろそろ世界樹2のパッケージ開けても良いかなー

実は昼頃に買ってきて、ずっとガマンしてるという。 そんな現在、夜八時。 初回特典(?)の CD は聴いた。

ともあれ、まだちょっと切りが悪いからもう少し粘ってから開けよう。 つーか睡眠時間の事を考えると、今日は開けない方が良い気もするが(苦笑

% [game] セカキュー2日記、序章

開けちまったぜ、呪いの箱を。

なんか前作のパスワードを書き写すのと今回のに入力するので 30 分近くかかったような気がするが気にしない。 すいません嘘です、結構イラっとしました。 やっぱ DS にもほんのちょっとで良いから外部記憶はあった方が良いよ。

なんか普通に安定したパーティを作ろうと思うと、いつの間にか前回と同じ構成になってしまいそうなので、今回は敢えて新職業を無理にでも入れるという方針で。 パラディン、ブシドー、バード、ガンナー、ドクトルマグスの五人で行こうと思う次第。 レンジャーが好きなのでバードの代わりに入れようか迷ったんだけど、まあ前作で十分使ったし、ということで。

なんか今回オッサン系グラフィックが充実してて、危うく全員オッサングラを選びそうになったんだけど、さすがにそれはどうかと思って二人は女キャラにした。 うん、逆に言うと三人はオッサン(笑

とりあえずペット (それって職業か?) 以外は最初から使える模様。 もちろんペットが使えるようになったらサーベルタイガーを選んで、名前は『げれげれ』ですよね。

パスワードを入力した場合、前作をクリアしていたら勲章が貰える。 HP+10, TP+10, 全能力+1 という、しょっぱなから使えるにしては結構ステキな性能。 さっそく前衛としては柔らかいブシドーに装備させてやろう。

システム的には大きな違いは無いようだけど、日付があるみたいなのがちょっと気になる。 あと、マップに使えるシンボルが増えててありがたい。(まあ少ないのをやりくりするのも楽しみだったわけだけど)

% [game] セカキュー2日記、毒のリンプンでいきなり全滅の危機

お約束だぁね〜

% [game] セカキュー2日記、すでに二回全滅

つーかさー、別にわしだってわざとそうしてるわけじゃないんだけど、FOE の巡回ルートを確かめるために近くで (だってマップ塗れてないうちは目視するしかないじゃん) うろうろしてるうちにうっかり触っちゃったわけよ。 で、全く逃げれないってヒドくね? 前は全滅しそうになったとしても、誰か一人くらいは生き残って逃げられたと思うんだがなー orz

鹿死ね。

あーもー、カニ歩きなんかよりも、まず『その場で足踏み』する機能付けてくれって感じだな。 やっぱ逃げやすくするためにはレンジャーが必要かなー。 一応ブシドーも逃走率 UP は付けれるけど、そんなのにスキルポイント使うのもったいないよ。 あー、まいった。

ピンチになるほど逃走確率が上がるのはアトラスゲーの美点だと思ってたんだけど、今回そういう補正無しなわけ?

% [game] セカキュー2日記、パーティー構成

新職業のガンナーとドクトルマグスは結構インチキくさいキャラだなー。

ガンナーは三属性の攻撃ができる上、味方全員の状態異常を治すスキルもある。

ドクトルはメディックと同等の回復スキルを持ち、さらに味方の能力値アップ系とか敵のアップ系効果の消去だとか、本来色んな職業がそれぞれバラバラに持っていたものをまとめて持ってる。 まあ、このゲームの場合全部のスキルを取得するのは不可能なんで、ある程度どこを伸ばすか決めて育てないと単に中途半端なキャラになるのがオチだが、ちゃんと考えて育てればどんなパーティー構成でも足りない部分を補えるスーパーキャラクターだ。

ブシドーは各構えのスキルはあるけど、前作のような使用するものではなくなっている。 なので、構えごとの攻撃スキルがいきなり使えるようになっているので、かなり使いやすくなった感じ。


2008-02-22 [長年日記]

% [Rails] 微妙なバグ発見

まあ大勢に影響は無さそうだが、エラーが変なところで出て悩むという可能性はあるかも。

(actionpack-2.0.2/lib/action_view/base.rb)
298 template_extension = pick_template_extension(template_path).to_s
299 unless template_extension
300   raise ActionViewError, "No template found for #{template_path} in #{view_paths.inspect}"
301 end

to_s してるから 299 行目の unless ブロックが実行されることは絶対に無い。 直すとしたら、

299 if template_extension.empty?

とか?

% [雑談] ネスカフェ ドルチェ グストというのを買った

わりとカフェイン中毒のわしとしては、仕事中とかコーヒー紅茶の類いは欠かせないんだが、いちいちちゃんと落としてコーヒー入れるのもめんどくさくて、ほとんどはインスタントコーヒーを飲んでいた。 でも、まあさすがにいい加減もう少しちゃんとしたコーヒーが飲みたいよなーと思っていたところ、知り合いが結構お薦め評価をしてたんで思い切って。

でまあ、結構良いですよ、と。 何が良いって楽なのが。 詳しいことはリンクしたサイトの方でも見てもらうとして、簡単に特徴を述べるなら、

  • 使い方、超簡単
  • お手入れ、超簡単
  • 味、少なくともインスタントよりはずっと上

「要するにコーヒーメーカーなんでしょ?」と思うかも知れないけど、ちょっと違う。 や、コーヒーを作る機械なんだからコーヒーメーカーで正しいんだけど、たぶん普通の人が思い浮かべるそれのイメージとは違う。

まず、コーヒーを作って溜めておくわけではない。 コーヒーはその都度飲むときに一杯分ずつ作る。 タンクには『水』を入れておいて、飲むときにカプセルをセットして抽出という流れ。 『お湯』じゃなくて『水』。 でも電気ポットじゃないのでお湯を沸かすわけではない。

なのに抽出時には、いきなり熱いコーヒーが出てくる。 すごい楽。 お湯が沸くまで待つ必要とか無いの。

カプセルの単価が 40 円 50 円ほど (追記)800 円でカプセル 16 個(/追記) で、ちょっと高いと言えば高いけど (世の中には単価十何円の一杯ずつパックとかあるしね)、わしのようなものぐさな人間にはかなり適しているアイテム。 ちなみに希望小売価格が 19,800 円になってるけど、実質唯一の取り扱い店であるセブンイレブンでは 14,800 円。 でも、店頭販売してるのは北海道だけみたいなんで、その他の地域の人はちょっと面倒かもしれない。

% [game] セカキュー2日記、第二夜

ガンナーとドクトルマグスも逃走率 UP を持っていることに気付く。

しかしガンナーはアルケミストがいない分の属性攻撃戦力を担ってるし、ドクトルはメディックの代わりに回復のエキスパートになってもらわないといかん。

…… って、 よく見たら全員持ってんじゃんか、逃走率 UP。 なんだ、誰でも使えるスキルになったのかよ。

とは言え、誰に付けたもんか迷うんだよなー。 で、結局パラディンに全力逃走を付けてみたり。 付けたは良いけど、どこまでレベルを上げるべきかも悩みどころ。

そう言えば、メディックの『キャンプ処置』はどうなったかなー。 前回あまりにも地雷だったんで、今回逆に使えるスキルに変身してたりして…… とか思っちゃうんだけど。

…… そして、また騙されると(笑

メディック入れないで良かった。 入れてたら悩んで眠れなそうだ。

% [game] セカキュー2日記、やっぱレンジャー良いなー

ちょっと事情があってレンジャーを一人作ったんだけど、やっぱスキルリスト見てると使いたくなってくる。 先制ブーストとか危機感知とか重要だよなー。

アザーズステップの取得条件が厳しくなってるような気がするけど、前作でどうだったかあんまり憶えてないんで実際のところはわからん。


2008-02-23 [長年日記]

% [雑談] ホットビールとか、その他ビールの雑談

朝刊を見ていたらキリンビールのどこだかのレストランで「一番搾りスタウト」を使ったホットビールとやらを出しているという記事があって、ちょっと気になったのでググってみたり。→ 『KIRIN_一番搾り スタウト_おいしい飲み方

で、何の因果かこのビールが今我が家にはたくさんあって、それじゃあまあ一本くらい無駄にしてみようかなと試しに作ってみた次第。 って言うか、なんでわしは朝っぱらからビール飲んでんだ?

…… 予想どおり、あんまりおいしくなかったです orz

お好みでシナモンスティックや角砂糖を入れろとなってるんで、そこら辺があればも少し違ったのかもしれないし、なんつーか人それぞれ好みもあるかとは思うけど、わしはもう良いや。 ちなみにどんな味かを一言で言うと…… なんかすっぱい? ホットオレンジジュースが冷たい状態よりすっぱいのと同じような話なんだろうか。

それはそれとして、このビールは (普通に飲むなら) そこそこいけるよね。 まあスタウトなら間違いなくギネス・エクストラスタウト (近所の酒のディスカウントショップで買えるんでわりとよく飲む) の方がうまいと思うけど、一本 265 円するんだよなー。 で、キリンのはスーパーで 194 円。 「70 円も違うなら」と我慢できる程度には十分うまいと思う。 うん、どうせあたしゃ貧乏人さ。

あとギネスの場合ドラフトが 270 円とほぼ同じ値段なんで、いつもどっち買うか迷っちゃうんだよな。 ドラフト缶のあの泡と同じものを、エクストラスタウトのボトルから自分で作り出すのはわしには無理。 ドラフト缶は泡のためだけに買う価値はあると個人的には思いまつ。

ところで、黒ビールは他のビールと違って、ちびちび舐めるものだと思うんだけどいかがか? チーズとかかじりながらギネスビールを舐めるのが至福。 まあ、メタボとか怖いのでチーズは滅多にかじらないけど(苦笑

% [雑談] DVD ぽてまよ6

届いた。 お楽しみの文化祭その2を見る。

飛び道具

卑怯すぎるぞw

誰をも魅了する笑顔

笑ってないしw

そんな感じでとうとう特典アイテムがコンプリートしてしまったので、某氏におかれましては適当な時期を指定していただければ送り付けいたしますので、よろしくお願いいたします。(日本語変)

% [FreeBSD] ようやく家の環境を 6.3R にアップグレードした

いやー、やろうやろうと思いつつだらだらと先延ばしにしていたんだが、いーかげんやらんとなーと思ってがんばった。 まあ、手順的には Announcement に書かれてるまんま freebsd-update を実行しただけなんで大したこたないんだけど。

ちなみにわしの場合はモニタ&キーボード無しで常に ssh でいじってるマシンなので、一回目のリブートの後、ユーザランドをインストールした段階ですぐリブートはせずに、ssh のセッションを切らないまま sshd だけリスタートして (/etc/rc.d/sshd restart) 別の端末から新たに ssh 接続できるのを確かめた。 そうしないと万が一新しい sshd で接続できなかったりした場合に、泣きながらローカル端末を接続して作業するはめになるから気を付けないと。ザ・経験談(泣

まあ、今回は特に問題は無かったけどね。

% [game] セカキュー2日記、FOE はスルー決定か?

Lv15 で 5F まで到達という辺り。 まったりプレイ中。 焦ると死ぬからね。

もうちょっとレベルが低かったときに、試しににっくき鹿を踏ん張って倒してみたんだが (二人死んだけどな)、経験値 0 でひっくり返る。 なんですとー!!

ドロップアイテムがどうなってるかはわかんないけど (少なくとも一回だけ倒したときは何も出なかった)、経験値 0 なら基本的には心置きなくスルーできるってことだなー。 というわけで、現在 FOE 撃墜スコアは 0 。(二人生き返らせるお金がもったいなくてリセットしたから :-p

そういや 1F の FOE を倒すクエストをやってみたら、いきなり先制攻撃で攻撃の要のブシドーが即死して泣いた (そのときのレベルは 10 まで行ってなかった気がするが)。 そろそろ倒せるようになったかな。

前作もそうなんだけど、開発者の思惑としては FOE ってのは通常、戦闘は避けるものであってアホみたいに強いのは当たり前らしい。 でも、前作ではどうも FOE を倒せるようになるまで先に進まないで稼ぐ人とか結構いたらしく、かまきりを倒せるようになるまで延々と B3F 辺りをうろちょろしてた、なんて話もあったとか。 かまきりなんて、B5F のボスより強いと思うんだけどね(苦笑

まあ、そんな話もあってか、今回は全体的に FOE がさらに強く設定されてるのかも。 つまり全力で見逃せという感じで。 ちなみにわしは、極力触らないようにしてるし、運悪く触ってしまったら即『全力逃走』でさよならしてる。


2008-02-24 [長年日記]

% [雑談] どうでもいー話

昨日、

なんでわしは朝っぱらからビール飲んでんだ?

とか書いたんだが、これだけだとなんか『朝から一日中酒飲んでた』みたいにも読めるな(苦笑

一応弁解しておくと、飲んでませんからね、そんなには。 外で飲むときなんかは別としても、家ではそんな飲む方じゃない。 ビールなら飲んだとしてもせいぜい 350ml 缶三本くらい。 普通は一・二本だし、全然飲まない日もたくさんある。 というか、飲まない日の方が多いはず。

…… つーか、ビール高いよね(苦笑

でも、わしはアルコールに関しては量より質を取るタイプなので、発泡酒とかを毎日飲むくらいなら何日かおきにちゃんとしたビールを飲む方がマシ。 まあ、そもそも毎日飲みたくなるタイプじゃないってのもあるけども。

% [game] セカキュー2日記、現在の育成方針

ブシドーは構えは居合だけ取得して、『首討ち』での即死と氷攻撃に特化。 『白刃取り』はすごく魅力的だけど、取得条件が厳しすぎるので今のところは無視。

パラディンは『フルガード』取得のためにフロント/バックガードを強化中。 属性ガードはバラで取るか TEC を上げて『マテリアルガード』を取るか悩みどころだなー。

ドクトルマグスはパーティーにメディックがいないので完全に回復専門。 もし攻撃型にするなら、ダークハンターやカースメーカーと組むと威力を発揮しそうだよね。

ガンナーはイマイチ方針が固まらないので、ドラッグバレット Lv2 (毒回復のため) 以外はだいたいまんべんなく。 各属性ショットはまだ全部 Lv1 (消費 TP の問題もあるんで)。 今のところは『跳弾』のために『銃マスタリー』を強化中。 氷はブシドーがカバーしてるので、今後はそれ以外の属性を鍛える方向になるのかな。

バードは完全に『いるだけでなんとなく嬉しい人』を目指してる。 舞曲三つと採取を Lv1 ずつ取っただけで、あとは丸々 LUK ブースト → ホーリーギフトへ。 Lv16 現在、ホーリーギフト Lv3。 ギフトをマスターしたら、次は奇想曲かなー。 その前に FOE 対策で『全てへの子守唄』なんかも良いかしら。

% [game] セカキュー2日記、第一階層突破

レベルは全員 21 で。 前作同様、お供の FOE がごっそりいるが、バードの子守唄で眠らせてから事にあたったおかげで、乱入される前になんとか決着を付けることができた。 チキンくさいが、このゲームはそれで良いんだ。

でも一匹も乱入してこないまま終わったせいで、周りにいた連中が何者だったのかは不明という。 まあ、いずれ復活する頃には普通に戦えるレベルになってるだろうし、見るのはその時で十分だな。

で、いよいよペットが作れるようになったんで、予定どおり「げれげれ」を誕生させてみたが、なんとも微妙なスキル構成で困る。 どういう位置付けで使うべきなんだろなあ、こいつは。

『野性の勘』という伐採、採掘、採取を兼ねたスキルがあるんで、「これはアイテム採取用キャラか?」と思ったんだけど、取得条件が LUK, TEC それぞれレベル 5 必要だったりして、それだと必要なスキルポイントはレンジャーで採取スキル三つにつぎ込むのと変わらんという事実。 微妙……

% [game] セカキュー2日記、地図に表示されない FOE 登場

第二階層に入り、空飛ぶ FOE に続く新種、地図に表示されない FOE が登場。 ただでさえ FOE が強くて触ると高確率で全滅だってのに、なんて鬼畜な(苦笑

やっぱチキンプレイヤーとしては、全員に逃走率 UP 付けて、かつ全力逃走は Lv5 まで上げるべきかな。


2008-02-25 [長年日記]

% [雑談][私信] 把握しますた > 某氏

前回と同じような感じで近いうちに手続きしやす。 (さすがにその時にはちゃんとメールするっす)

しかし、こういう関係者以外わからんような話を書くのはどうなんだろう、とか思ったり。 んー、でもここはブログじゃなく Web 日記だからねー。そーゆーもんだよね。 まー、読者層が結構かぶってる可能性高い気がするんで、一緒に読むと意味がわかったりとか、そういうのも Web 日記の楽しみだったと思うんだ。


2008-02-26 [長年日記]

% [雑談] 外がすごい地吹雪でワロタ

いや、笑いごとじゃないとは思うんだが、わしは今日は別に外に出る用事も無いので超他人事というかね。 外に出てる人はほんとにご苦労さまでございます。

% [clip] sm2426055 (イチローの素晴らしいプレーの数々を英語の実況でまとめてみた)

アメリカの解説者おもすれーなw

理解に苦しむね

二塁に投げるべきだったよ

にワロタ。

(ニコが見れない人のために一応説明しておくと)

ランナー一二塁で二塁ランナーがイチローというシチュエーション。 で、ダブルスチールかけたんだけど、キャッチャーは三塁に投げてイチローはセーフだった (なのでもちろんオールセーフ) という場面での解説者のセリフ。 たぶん、日本の解説者はこんなこと言わない(苦笑

% [game] セカキュー2日記、そろそろ二度目のボスかな?

10F に到達してミッション受けてから出直せと追い返されたところ。 レベルは全員 30 。 ホーリーギフト Lv5 が効いてるのかもしれないが、わりとサクサクレベルが上がってる感じ。

ドクトルマグスは当初メディックと同じように後衛に配置してたんだけど、すっかり攻撃力・防御力が上がってきて後に置いておくのはもったいないってことで前衛に定着した。 前衛が三人になったおかげで攻撃が分散され、ブシドーも死ににくくなった気がする。

目下の懸案事項は、めんどくさくて放置してある三日間篭るクエストをいつ実行するか。 前作の五日篭るやつはレンジャーがいたから楽だったんだよな。 今回は裏技ポイントも無いみたいだし、エンカウント率低下のスキルが無い状態だとかったるくてかなわん。

最初の方の二択イベントでリスに糸を取られて涙目になってから、ずっと糸は二個持ち歩くようにしてたんだけど、今回ようやくそれが役に立った。 つーか、結果が気になってどうしても二択イベントをスルーできないダメなわし。 ドラクエでタンスを見ると調べなきゃ気が済まなくてサーセンw


2008-02-27 [長年日記]

% [game] セカキュー2日記、第二階層突破

8F の宝石が見付からなくて延々歩き回ってるうちにレベルが 39 とかになっていた。 あんなところにあるなんてヒドいよ orz

で、10F のボスはレベル上がりすぎで楽勝かなーと思ったんだけど、思ったほどではなかった。 まあ、際どいシーンはほとんど無かったんで、楽だったと言えば楽だったんだろうけど。

第三階層はなんとなく予想していた通りの地形で目が痛い。 壁と通路の見分けが付きにくいのが無駄にリアルだな(苦笑

10F のボスが炎を使うっていうんで、ファイアガードを Lv5 まで上げてみたんだけど、前回のように無効能力は付かなかった。 さすがにインチキすぎると思ったのかね。 でも Lv10 まで行けばもしかしたら…… と考えると、これ以上レベルを上げるかどうか非常に悩ましい。

そろそろ下層の FOE を狩って微妙に埋まってなくて美しくないマップをキレイにしようしてみようかなーとか思ったり。


2008-02-28 [長年日記]

% [clip][FreeBSD] FreeBSD 7.0-RELEASE Announcement

とうとう来たか。 だがこいつを活かせるマシンが無い...orz

ざっと適当訳してみる。 ちゃんとした説明が欲しい人はしばらく待ってるとたぶん大地さん辺りの記事がどっかに載るであろう。

  • すんごく性能アップ
    • 有名どころのデータベースやその他のベンチマークにおいて、性能やマルチプロセッサ時のスケーラビリティが劇的な向上を見せている。
    • 通常稼動時で FreeBSD 6.X に比べ最高 350% の向上。
    • 高負荷時だと 1,500% にも。
    • これは、Linux カーネル (2.6.22 or 2.6.24) に比べて 15% ほど良い。
    • 以下の件がこの性能アップに貢献している。
      • 1:1 スレッドモデルである libthr がデフォルトに。
      • IPC、ネットワーク、スケジューラに関する進化したロック機構 (訳注:ジャイアントロックが減ってるという話だと思われる)
      • SMP に重点を置いた最適化。
    • いくつかのベンチマークは 8CPU まで線形にスケールすることを示している。これはマルチコアシステムに対して有利に働くだろう。
  • ULE スケジューラが大きな性能アップと良い応答性をもたらす。(ただし 7.0 ではまだ 4BSD スケジューラがデフォルトで、7.1 から ULE がデフォルトになる)
  • ZFS の実験的なサポート。(訳注:ちゃんとしたサポートを目指してたような気がするけど、結局 experimental の文言は取れなかったんだね)
  • gjournal によってファイルシステムにジャーナル機能を設定できるようになった。gvirstor は仮想ストレージプロバイダ (訳注:良い訳が思いつかん) として機能する。
  • XFS ファイルシステムを読み込みのみサポート。
  • unionfs が復活。
  • iSCSI イニシエータ。(訳注:イニシエータってのは要は SCSI で言うところのホストバスアダプタにあたるもので、iSCSI はネットワークで繋げるものだから SCSI のように専用のハードウェアは必要無く、ソフトウェアでイニシエータを構築するのが一般的なのだとか。つまりはよくわかんないけど、iSCSI 機器が使えますよという話で終了だと思われる)
  • いくつかのネットワークドライバにおいて、TSO と LRO をサポート。(訳注 TSO とか LRO が何なのか知らない)
  • SCTP (Stream Control Transmission Protocol) の実験的サポート。(FreeBSD はこれのリファレンス実装になろうとしている)
  • ワイヤレス (802.11) サポートの向上。
  • ネットワークリンクをまとめる機能 (訳注:自信無い) である lagg(4) を OpenBSD から取り込み。
  • BPF をネイティブコードに JIT コンパイルするようになった。これによりパケットキャプチャの性能が増す。(訳注: BPF は Berkeley Packet Filter だっけ?)
  • ARM ベースの組み込み機器の開発に対するさらなるサポート。
  • jemalloc という新しい高スケーラブルなユーザレベルメモリアロケータ。
  • freebsd-update(8) が公式にリリース間のバイナリアップグレードを提供。
  • 付属ソフトウェアのバージョン情報は省略。

あー、マルチコアなマシンが欲しいなー。

% [game] PS2 の NiGHTS が先週発売されていたことに気付いた、今

なんたる不覚。世界樹に気を取られすぎ!! で、近所の店ではもうすでに売り切れていたという……orz

しかたにゃーのでアマゾンさんに頼むことにした。

これらの商品の発送可能時期: 2008/2/29

1 "ナイツ ~星降る夜の物語~ 特典 ナイツ・パペッチフィギア MODEL NO.X001付き"
Video Game; ¥ 3,570

1 "ナイツ into dreams ~ナイトピア・ドリームパック~(初回限定版: 復刻絵本「翼がなくても空は飛べる」同梱)"
Video Game; ¥ 4,594

…… あれ、なんか変じゃね? つか、一つ目の方は余計じゃね? Wii 持ってないのに何やってんの、わし(笑

すいません、そろそろ次世代機ってやつを何か一つくらい買っても良いんじゃないかと思ってまして。 まあ今のところ一番買う可能性が高いのは Wii なんだけど。 PS3 とか箱○ とか買っても、うちにはゴミのような旧世代テレビしか無いので、性能を活かせません。 でも、みんゴル3はやりたいし、PSP で PS1 のゲームやりたいし、PS3 はちょっと欲しいんだが。

% [Scala] Java Generics 以外の 2.7.0 における変更点

Generics に気を取られて他の変更点をチェックしてなかったんだけど、2.7.0-final が出たのを機会にちゃんと Change Log を見てみた。

The Scala compiler generates now for every case class a companion extractor object.

ということで、以前「case class は、実質 apply と unapply が自動的に定義されたオブジェクトと同等だと言えるだろう。」と書いたことがあるんだが、今回から実際にそういうオブジェクトが定義されるようになったということらしい。

このことが何をもたらすかと言うと…… 何をもたらすんだろうね? とりあえずどう違うかとしてはこんな↓ 感じか。

Welcome to Scala version 2.6.1-final.

scala> case class A(e:String)
defined class A

scala> A
<console>:7: error: missing arguments for method A in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
       A
       ^
Welcome to Scala version 2.7.0-final (Java HotSpot(TM) Client VM, Java 1.5.0_13).

scala> case class A(e:String)
defined class A

scala> A
res0: A.type = <function>

case class 自体を値として持ち歩けるようになったんで、メタプログラミングの役に立つかもしれない。 あとまあ、『同じようでありながら微妙に違う』という状態から、『同じ』になったことも同様に役に立つのかもしれないね。


2008-02-29 [長年日記]

% [Rails] 教訓『何か意味不明な挙動に悩まされたら、まずキャッシュ機能を疑え』

本日の戦犯→ ActionView::Base.cache_template_extensions

template_exists? の結果を使ってごにょごにょ…… みたいな機能を作ってたんだけど、テストで動的に append_view_paths とかしたときに想定通り動いてくれなくて、調べてみると template_exists? の結果が変。 で、延々調べて調べて調べてシラ…… もー知らねー!!

てな辺りでようやく、上記のキャッシュ機能が怪しいことに気付く。 で、これを false にしてみたら解決。 ちょっとトリッキーなことしようとするとすぐこれなんだから、まったく、キャッシュはまったく :-(

% [Scala] 2.7.0-RC3

ちょw final から RC3 に戻ったんですけどwww

何があったんだ?

% [game] セカキュー2日記、火力が足りなかった

レベル 49 で 15F の二人組に突貫。 ボコボコにされた。(つまり全滅)

とりあえずクエストが五つくらい残ってるんで、それをこなしながら装備を整えたりレベル上げたりしよう。 しかしレベル 50 間近で 15F 突破に苦労するって前作より厳しくないかなあ。 過去の日記を見返してみると、B17F でレベル 49 とか書いてるし。 ダンジョンの階層が前回と同じだとして、もしレベルの上限も同じく 70 だとすると、最後の方が辛くなるような気が……

まあ、今回のパーティーはレンジャーがいないんでギリギリ状態の戦闘にはちょっと弱いという感じはあるんだけど。

ところで属性ガードは Lv8 で無効化がついた。それ以上上げると吸収。 でも今回、(ガードスキル全般に言えるけど) ガードが必ず発動するとは限らなくなってるんで、イマイチ信頼しきれないのが珠に傷。 マスターまで上げると違ったりするのかなあ。


トップ 最新 追記

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

RSS はこちら

jijixi at azito.com