トップ 最新 追記

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

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|

2007-07-01 [長年日記]

% [独り言] もう Web 関係は避けて通れない…

…と何年も前から思っているにもかかわらず、どこから手を付けて良いのかわからなくて、結局避けて通ってきたツケが今来てるような気がする。

なんつーか、わしのダメなところとして、「いずれ必要になるぞ」という事柄に力を注ぐことができないというのがある。 「今まさに必要」という事には、かなり力を入れることができるんだけど、今必要でないことは、どうしても後回しにしてしまう。

もちろん、ものによっては後回しでも良いこともあるだろうけど (例えば、いざ必要になったときでも 1 日がんばればできることとかね)、なかなかそうも行かないものが多い。 特に『実績』ってやつなんかはそうだ。 実績ってのは、積み重ねのことであり、積み重ねってのは一朝一夕でできるものではない。

そうして、実績作りを後回しにしてきた結果……行き詰まる...orz


2007-07-03 [長年日記]

% [OCaml][雑談] OCaml はダメなのか?

なんか催促されたっぽいので、件の OCaml Language Sucks についてだらだらと。

まあなんつーか、この記事は Matz さんが取り上げる以前に programming reddit 経由ですでに見ていて、「そんなに Common Lisp が好きなら Common Lisp で仕事すりゃ良いんじゃね?」で終了だったんだけど。

全体的に、標準ライブラリが貧弱なのは OCaml 使いなら誰でも感じてることだろうけど、その他の話に関してはほとんど言いがかりに近い些細な事って気がするね。 どれもこれも、ちょっとした慣れの話であって、批判に値する事柄というよりは単に好みの問題じゃないのかな。

OCaml の基本的なポリシーには『厳格な型付け (暗黙のキャストなんてもってのほか)』というのがあると思うんだけど、それを良しとするなら文句を言う筋合いの無い事柄が多い。 逆に良しとしないなら、OCaml 使うのなんて止めちゃえば?という感じ。 「明示的にキャストしないと int に float が足せない」とか、何言ってんの、そこが良いんじゃないか、と。

あと細かい話をすれば、Record field naming hell なんかはオブジェクトを使えば解決できる。 速度を気にしなければレコードよりオブジェクトの方が便利なことは多い。 逆に言うと、レコードは色んな事を犠牲にしている代わりに、全てが静的に (コンパイル時に) 決まるので、辞書ベースのオブジェクトに比べて相当速いらしい (自分では実験したことないけど、たしかメーリンリストか何かでベンチマーク結果が出てた)。 ちなみに、オブジェクトみたいな偽物じゃなく、本物の多相レコードが使いたいという人は SML# をどうぞ。

あと、マクロはあるよ。Camlp4 っていう無駄に強力なのが。わしは全く使いこなせないけど。 そこまで強力なのが必要無ければ cpp を利用したりも可 (参考)。

% [Ruby][Rails][Mac] もろもろの事情により、Ruby on Rails をいじり始めたりとか

まあ、元々全然興味が無かったわけでもないんだけども、何となくきっかけが無くて手を付けにくかったりしたわけで、ようやくかよ、って感じだけど。 ともあれ、事態がどう転んだとしても、無駄にはなるまいと思ってエイヤっとね。 とっかかりの勢いってのは大事だよ、うん。

とりあえず、MacPorts で mysql5+server と rb-rails をインストール。 あと、rails.vim とかも。

その後、チュートリアルを見ながら練習。 そこで、実は Locomotive っていうオールインワンパッケージがあるのが判明して、ちょっと涙する。 試験用の Web サーバを用意するのに便利だから、結局 Locomotive もインストールしてしまって、最初に入れた rails が無駄っぽくてせつない。

チュートリアルで作った cookbook2 は普通に動いてくれたんだけど、るびまの過去記事を参考に挑戦したユニットテストの練習がうまくいかなくて悩む。 例とまったく同じ構成にしてるつもりなんだけど、@topic_1 が nil だと言われて RutimeError が出るんだよなあ。 fixtures がうまく読み込まれてないのか、そもそもデータベース側に何か問題があるのか、はてさて。 結局何だかよくわかんなくて、とりあえず放置して先に進んでみたりとか。

初期段階でテーブルを作成するとき以外、SQL のこととかは、あんまり気にしなくても良いっぽいし、テーブル作って script/generate scaffold で雛形を出力すれば、それだけで何だかそれっぽいものができあがってるのは大したもんだなあ、と思う。 まあ、もっと細かいことをやり始めたときに、どれほど手間がかかるかは、まだわからんけども。

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

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


2007-07-04 [長年日記]

% [Rails] fixtures に書いた各アイテムの扱い

昨日のユニットテストがうまくいかない件だが、test/test_helper.rb を読んでようやく意味がわかった。 どうも、るびまの記事の時点と現在では多少デフォルトの設定が違ってるらしい。 件の記事だと、

asssert_equal(1, @topic_1.id)

と書いてたんだけど、現在は、

asssert_equal(1, topics(:topic_1).id)

と書くのが正しいようだ。topics は fixtures の名前だね。 もしくはテストケースクラスの self.use_instantiated_fixtures を true に設定してやれば @topic_1 って書き方もできるみたいだけど、遅いらしいので無理してやるほどのもんでもないだろう。

ともあれ、これですっきりした。

% [JoCaml] 今さらだけど parallel or

なんか、ついうっかり Haskellで学ぶ並列プログラミング(その3)並行プログラミングと並列処理を読みふけってしまったり。 そしたら、前に並列論理和を JoCaml で書いてみようと思いつつ、そのまま忘れ去ってたのを思い出して書いてみたりして。 あれ……こんなことしてて良いんだっけ?

% cat por.ml
let timeout_sec = 2

let (||||) a b =
   def left(true)  & result() = reply true to result
    or right(true) & result() = reply true to result
    or left(false) & right(false) & result() = reply false to result
   in
   def timeout() & wait() = reply false to wait
    or return(r) & wait() = reply r to wait
   in
   let with_timeout f =
      spawn (Unix.sleep timeout_sec; timeout()) & return(f());
      wait()
   in
   spawn left(with_timeout a) & right(with_timeout b);
   fun () -> result()

let (|||>) a b = (a |||| b)()

なんか単純に書いたら寂しすぎたので、両方止まらない計算だった場合に適当にタイムアウトして false を返すようにもしてみた。 まあ、その止まらなくなったプロセスを殺す方法がわからんので、実際無限ループだったりすると CPU 食われまくってアレだけど。

# #use "por.ml";;
val timeout_sec : int = 2
val ( |||| ) : (unit -> bool) -> (unit -> bool) -> unit -> bool = <fun>
val ( |||> ) : (unit -> bool) -> (unit -> bool) -> bool = <fun>
# (fun()->true) |||> (fun()->Unix.sleep 200;false);;
- : bool = true
# (fun()->Unix.sleep 200;false) |||| (fun()->Unix.sleep 200;false) |||> (fun()->true);;
- : bool = true

実行例だけ見てもわからないと思うけど、ちゃんと実行した瞬間に (200 秒待ったりせずに) true が返ってきてる。

# (fun()->Unix.sleep 200;false) |||| (fun()->Unix.sleep 200;false) |||> (fun()->false);;
- : bool = false

2 秒でタイムアウトするので、この例でも 200 秒待ったりしないで 2 秒後に結果が出る。

% [Rails] JavaScript をまったく書かずに Ajax

るびまの Rails 記事 (第 4 回) を参考にしつつ、この前練習で作った cookbook2 を改良して遊ぶ。

link_to_remote と render :partial で、項目をクリックすると中身を展開ってのを実装したりとか。 その間、JavaScript の記述量ゼロ。 いやはや、Rails って大したもんだね。 純粋に Ruby のコードとして見るとキモさ満点だけど、Ruby がどうのこうのを置いといて、単なるフレームワークとして見ると、さすがによくできとると感心せざるを得ない。

問題は、せっかくこう楽しんでも、その楽しさを伝えるサンプルコードをうまいことここに貼れないことだなあ。 実際に自分で書いてる部分はかなり少ないんだけど、そこだけ貼ってもわからんだろうし、かと言って自動生成されたコードは全部貼るにはデカすぎるし、にんともかんとも。

% [独り言] さて、がんばろう

とは言え、どの程度の期間が必要か、全く見積もれないのがなさけないなあ……とほほ。


2007-07-06 [長年日記]

% [雑談] 仕様の検討とか、基礎部分の設計に悩んで、一行も書き始められないときの焦燥感ったら、もう……

いくらボトムアップに組むと言っても、完成時のイメージがまったく無い状態じゃ始められないと思うわけで……でも、ある程度思い切って、見切り発車しちゃう勇気も必要なのかなーとも思う。

なんつーか、わしって、後々の面倒事を心配しすぎるところがあるのかなーと。 何にも書き始めていないときから、すでにリファクタリングとか設計変更のことを心配している。 どうせ、どんだけ準備万端にして始めたつもりでも、大抵の場合、結局それらはやらなきゃならないはめになるんだから、適当なところで見切りを付けるのも大事だよなあ。

% [雑談][Mac] 集中したいときには Noise.app を

考え事をしたいときなんかは、よくシャワーを浴びたりするんだけど、それというのも、あの水のサーっと流れる音が良い具合に周りの雑音を消してくれるからだったりする。

人それぞれだろうけど、わしの場合、集中の妨げになる最たるものは周囲の雑音だ。 特に規則性の無い音というのがどうにも癇に触る。 そんなわけで、以前は何かしら音楽を流しておくという対策をしてたんだけど、何年か前に Noise.app の存在を知ってからは、もうこいつが手放せない。 つーか、わしの場合、効きすぎてヤバい(苦笑

長風呂な方ではないんだけど、考え事しながらシャワーを浴びてると、気付いたら一時間くらい経ってた…とか結構あって (水不足な地域の人に怒られそうだ)、この Noise.app を使ってると、それと同様のことがいつでも起こり得る。 まあ、必要なことだけをする方向に集中できれば良いんだけど、ふとした拍子に全然関係無い方向に集中しちゃったりするから危険だ。

そんな感じで、ヘッドホン使ってノイズを流してると、ほんとにヤバいので (思考が変な方向に行っちゃっても、自分で修正できないくらい)、最近はヘッドホンは使わずにスピーカーから音を出すようにしてる。 まあ、それでもわしにとっては、十分強力な集中アイテムなのだが。

というわけで、集中力不足でお悩みのかたは、試してみてはいかが? Mac 以外の人は、適当に pink noise generator とかでググってみれば何かしらあるんじゃないかね。


2007-07-07 [長年日記]

% [独り言] あーもー空回りばっかしてて、ちっとも先に進まねーー

自分の無能さがせつない...orz

% [Erlang][LLSpirit] キミならどう書く 2.0 - 2007 - その 1 (問題 1 : 油売り算)

こんなことしてる場合かなー?という焦りもあるわけだが、まあ息抜きも大事だよ。 煮詰まりすぎると、しなくて良い失敗しちゃうもんだし。

というわけで、Erlang で書いてみた。 つーか、これって並行処理言語のための問題じゃない? 「えー?バックトラックが許されるのは小学生までだよね」 って感じで、後ろなんぞ見ずにただひたすら前に進むわけですよ。 そんで答が一つでも見つかったら、結果を待ってるプロセスに答を投げて終了。

出力のところが手抜きだとか、patterns 関数が醜すぎるとか色々アレだけども、やっつけ仕事なんで。 patterns のところは、綺麗に書こうと思ったらリストとかタプル使ってちゃダメだよね、たぶん。 dict とかの順番に関係無く値を取り出せる構造じゃないと。

てなところで、ちょっと長いけど以下ソース。

% cat abura.erl
-module(abura).
-compile(export_all).

main(A,B,C) ->
   Pid = spawn_link(fun result_proc/0),
   io:format("~b\t~b\t~b~nstart!!\n", [A,B,C]),
   spawn(fun() -> search(Pid, {{A,A},{B,0},{C,0}}, []) end),
   ok.

search(Result, {{_,X}, {_,Y}, {_,Z}}=Next, Prev)
      when is_pid(Result),is_list(Prev) ->
   New = [Next|Prev],
   case is_finish([X,Y,Z]) of
      true -> Result ! {result, New}, exit(finish);
      false ->
         case lists:filter(fun(P)-> not lists:member(P,Prev) end,
                           patterns(Next)) of
            [] -> exit(normal);
            Patterns ->
               lists:foreach(fun(Pat) ->
                  spawn_link(fun() ->
                     search(Result,Pat,New)
                  end)
               end, Patterns)
         end
   end.

is_finish([_,_,_] = L) ->
   Min = lists:min(L),
   case {Min, lists:delete(Min,L)} of
      {0, [A,A]} -> true;
      _ -> false
   end.

patterns({{A,X}=M, {B,Y}=N, {C,Z}=O}) ->
   DA = A-X, DB = B-Y, DC = C-Z,
   begin % A to B or C
      DB1 = lists:min([X,DB]),
      DC1 = lists:min([X,DC]),
      case DB1 of
         0 -> [];
         _ -> [{{A,X-DB1}, {B,Y+DB1}, O}]
      end ++ case DC1 of
         0 -> [];
         _ -> [{{A,X-DC1}, N, {C,Z+DC1}}]
      end
   end ++ begin % B to A or C
      DA2 = lists:min([Y,DA]),
      DC2 = lists:min([Y,DC]),
      case DA2 of
         0 -> [];
         _ -> [{{A,X+DA2}, {B,Y-DA2}, O}]
      end ++ case DC2 of
         0 -> [];
         _ -> [{M, {B,Y-DC2}, {C,Z+DC2}}]
      end
   end ++ begin % C to A or B
      DA3 = lists:min([Z,DA]),
      DB3 = lists:min([Z,DB]),
      case DA3 of
         0 -> [];
         _ -> [{{A,X+DA3}, N, {C,Z-DA3}}]
      end ++ case DB3 of
         0 -> [];
         _ -> [{M, {B,Y+DB3}, {C,Z-DB3}}]
      end
   end.

result_proc() ->
   receive
      {result, R} ->
         lists:foreach(fun({{_,A}, {_,B}, {_,C}}) ->
                          io:format("~b\t~b\t~b~n", [A,B,C])
                       end,
                       lists:reverse(R))
   end.
Eshell V5.5.5  (abort with ^G)
1> c(abura).
{ok,abura}
2> abura:main(10,7,3).
10      7       3
start!!
ok
10      0       0
3       7       0
3       4       3
6       4       0
6       1       3
9       1       0
9       0       1
2       7       1
2       5       3
5       5       0

検証してないけど、たぶん合ってるんじゃない? 全てのパターンを、全部別プロセスで並行処理してるわけだから、一応これも幅優先探索……のはず。

% [Erlang][LLSpirit] 油売り算・改

やっぱりどうしても patterns 関数が気になるので、orddict を使って書き直した。 出力は同じなので省略。

% cat abura.erl
-module(abura).
-compile(export_all).

main(A,B,C) ->
   Pid = spawn_link(fun result_proc/0),
   io:format("~b\t~b\t~b~nstart!!\n", [A,B,C]),
   spawn(fun() ->
      search(Pid, orddict:from_list([{a,{A,A}},{b,{B,0}},{c,{C,0}}]), [])
   end),
   ok.

search(Result, [{a,{_,X}}, {b,{_,Y}}, {c,{_,Z}}]=Next, Prev)
      when is_pid(Result),is_list(Prev) ->
   New = [Next|Prev],
   case is_finish([X,Y,Z]) of
      true -> Result ! {result, New}, exit(finish);
      false ->
         case lists:filter(fun(P)-> not lists:member(P,Prev) end,
                           patterns(Next)) of
            [] -> exit(normal);
            Patterns ->
               lists:foreach(fun(Pat) ->
                  spawn_link(fun() ->
                     search(Result,Pat,New)
                  end)
               end, Patterns)
         end
   end.

is_finish([_,_,_] = L) ->
   Min = lists:min(L),
   case {Min, lists:delete(Min,L)} of
      {0, [A,A]} -> true;
      _ -> false
   end.

patterns(Next) ->
   orddict:fold(fun(Key,{Cap,Now},Acc) ->
      Rest = orddict:erase(Key, Next),
      orddict:fold(fun(K,{C,N},A) ->
         Def = lists:min([Now,C-N]),
         case Def of
            0 -> A;
            _ -> 
               [lists:foldl(fun({K_,V},R) ->
                   orddict:store(K_,V,R)
                end, Next, [{Key,{Cap,Now-Def}}, {K,{C,N+Def}}])
                | A]
         end
      end, [], Rest) ++ Acc
   end, [], Next).

result_proc() ->
   receive
      {result, R} ->
         lists:foreach(fun([{a,{_,A}}, {b,{_,B}}, {c,{_,C}}]) ->
                          io:format("~b\t~b\t~b~n", [A,B,C])
                       end,
                       lists:reverse(R))
   end.

どうせなら、枡も三つ限定じゃなく可変長にしてやろうかと思ったけど、さすがにそれは思い留まった。


2007-07-08 [長年日記]

% [Scala] Actor の弱点? (というほどではないと思うが、気を付けた方が良いこと)

Scala のパターンマッチは、型を指定したマッチングができるんだけど、

scala> def f(a:Any) = a match {
     |   case i:Int => println('int)
     |   case s:String => println('string)
     | }
f: (Any)Unit

scala> f(1)
'int
unnamed0: Unit = ()

scala> f("hoge")
'string
unnamed1: Unit = ()

残念なことに、Generics な型の場合は、型パラメータまでチェックできないので、例えば List[Int] と指定しても、List なら何でもマッチするパターンになってしまう。 この辺は、Java の class に落としこんじゃう仕様の呪いかなあ。

そんでまあ、Actor のメールボックスも、メッセージの型を判別する仕組みは同じなので、

% scala -unchecked

scala> import actors.Actor._
import actors.Actor._

scala> val a = actor {
     |   receive {
     |     case n:List[Int] => println(n)
     |   }
     | }
<console>:8: warning: non variable type-argument Int in type pattern is unchecked since it is eliminated by erasure
    case n:List[Int] => println(n)
           ^
a: scala.actors.Actor = scala.actors.Actor$$anon$0@312942

scala> a ! List("hoge","fuga")
List(hoge, fuga)
unnamed0: Unit = ()

こんな感じになる。 receive の部分の意図としては、List[Int] 型のメッセージが来たときだけ表示してほしいわけだけど、型パラメータのチェックができないので、List[String] が送られてきても、マッチしてしまうわけだ。

そんなわけで、アクター間で型安全を確保したいなら、Generics なデータ構造をそのまま投げたりはしない方が良さそう。 具体的には、タプルで型を構築して送りましょう、って感じか。

% [Scala][LLSpirit] Scala & Actor で油を売る

まあ、Erlang でやると、当然対比として Actor でも書いてみたくなるのが人情ってもんだ。 ちなみに、Generics なデータをそのまま投げるな、とか書いといて、この例では思いっ切り投げてるじゃん、というツッコミは却下。 だって、さっきの話は、これ書いてて気付いたんだし。

% cat abura.scala
import scala.actors._
import scala.actors.Actor._
import scala.collection.immutable.Map

object Abura extends Application {
   type State = Map[String,(Int,Int)]

   def calc(a:Int,b:Int,c:Int):Unit = {
      val pid = result_proc
      Console.printf("{0}\t{1}\t{2}\nstart!!\n",a,b,c)
      actor { search(pid)(Map(("a",(a,a)), ("b",(b,0)), ("c",(c,0))))(Nil) }
   }

   def search(result:Actor)(next:State)(prev:List[State]):Unit = {
      val new_list = next::prev
      if (is_finish(next)) {
         result ! ('result, new_list)
         exit('finish)
      } else {
         patterns(next).filter { p =>
            ! prev.contains(p)
         } match {
            case Nil => exit
            case pats =>
               pats.foreach { pat => link { search(result)(pat)(new_list) } }
         }
      }
   }

   def is_finish(s:State) = {
      val set = for ((k,v) <- s) yield v._2
      val min = set.reduceLeft[Int] { _.min(_) }
      val rset = for (v <- set if v != min) yield v
      (min, rset.toList) match {
         case (0, List(a,b)) if a == b => true
         case _  => false
      }
   }

   def patterns(next:State) =
      next.foldLeft[List[State]](Nil) { (acc,elem) =>
         val (key,(cap,now)) = elem
         val rest = next - key
         rest.foldLeft[List[State]](Nil) { (a,e) =>
            val (k,(c,n)) = e
            val d = now.min(c-n)
            d match {
               case 0 => a
               case _ =>
                  List( (key,(cap,now-d)),
                        (k,(c,n+d))
                  ).foldLeft(next) { (r,e_) =>
                     val (k_,v) = e_
                     r.update(k_,v)
                  } :: a
            }
         } ::: acc
      }

   def result_proc:Actor = actor {
      receiveWithin(10000) {
         case ('result, r) =>
            r.asInstanceOf[List[State]].reverse.foreach { s =>
               val List( (_,(_,a)), (_,(_,b)), (_,(_,c)), _*) = s.toList.sort(_<_)
               printf("{0}\t{1}\t{2}\n",a,b,c)
            }
         case TIMEOUT => ()
      }
   }
}
% scalac abura.scala
% scala -cp .

scala> Abura.calc(10,7,3)
10      7       3
start!!
unnamed0: Unit = ()

scala> 10       0       0
7       0       3
7       3       0
4       3       3
4       6       0
1       6       3
1       7       2
8       0       2
8       2       0
5       2       3
5       5       0

書いてて思った Scala のちょっと切ないところ。

  1. 関数の仮引数部にパターンを書けない
    • いちいち分解すんのめんどくせ
  2. たまに総称関数の型パラメータを強制される (reduceLeft とか)
    • まあ、OCaml でもそういうシチュはあるし、型パラメータとして書ける分、Scala の方がキレイだって感じもするけども

それはそれとして、昨日の Erlang 版と出る結果が違うんだけど、どっか間違っとるんかなあ。 スレッドプールの数の関係で、順番が崩れてるってことかねえ。 でも、デバッグする元気は無いので、これで終了。

% [clip][Ocaml] Eliom (Ocsigen)

via らくがきえんじん

Ocsigen というのは OCaml で書かれた Web サーバとそれに付随するフレームワーク群らしい。 んで、Eliom はそのフレームワーク部分のページ生成関連モジュール…ということかな?

サンプルコードをさらっと眺めただけだけど、こういう風に書いたものが、コンパイルするだけで色んなことが静的に検査されると考えると、ちょっと鼻血が出そう。 余裕ができたら、もうちょっと詳しく勉強してみたいな。

% [Scala] Actor のメッセージ通信で Generics な型は要注意な件の続き (地雷踏んだよ)

うーん、まあ、そうは言ってもシーケンスな型だって安全にやり取りしたいよなー……と。 んで、ふと思って、こんな↓のはどうよ?と試してみたんだけど……

scala> import actors.Actor._
import actors.Actor._

scala> val a = actor {
     | receive { case List(x:int,y:int,z:int) => println(x+y+z) } }

……この時点で、盛大なスタックトレースを吐いてお亡くなりになった...orz

どれだけ盛大かと言うと、とてもじゃないけど、ここには貼れないくらいの分量で、script コマンド使ってログ取ってみたら 500 行くらいあったという盛大さ。 や、スタックトレースの部分は、その約半分で、残り半分はよくわからないけど例外発生箇所のソースコードがダンプされてるっぽい。

いろいろ試してみたところ、どうやら unapplySeq なパターンを使ってると軒並み死亡みたい。 なんかバグくさいな。つーか、インタプリタが死ぬんだからバグはバグなんだろうけど、それはそれとして、unapplySeq なパターンが使えないってこと自体がバグくさい。 本来は使えるべきだろう。

試しにこういうの↓をやってみると、

scala> import actors.Actor._
import actors.Actor._

scala> case class Hoge[A](x:A,y:A)
defined class Hoge

scala> val a = actor { receive { case Hoge(x:int,y:int) => println(x+y) } }
a: scala.actors.Actor = scala.actors.Actor$$anon$0@f7657b

scala> a ! Hoge("hoge","fuga")
unnamed0: Unit = ()

scala> a ! Hoge(1,2)
3
unnamed1: Unit = ()

うまく行く。

scala> import actors.Actor._
import actors.Actor._

scala> import scala.Stream._
import scala.Stream._

scala> val a = actor { receive { case cons(x,xs) => println(x) } }

これ↑は死んだ。 cons オブジェクトがパターンマッチ時に使ってるのは unapplySeq じゃなく unapply なんだけど、それでも死ぬってことは、むしろ case class だけが特別にセーフって状態みたいだね。

scala> import actors.Actor._
import actors.Actor._

scala> case class Hoge[A](args:A*)
defined class Hoge

scala> val a = actor { receive { case Hoge(x:int,y:int,_*) => println(x+y) } }
a: scala.actors.Actor = scala.actors.Actor$$anon$0@511816

scala> a ! Hoge("hoge")
unnamed0: Unit = ()

scala> a ! Hoge(1,2,3,4)
3
unnamed1: Unit = ()

こんな↑感じで、可変長でも大丈夫。 case class がこういう状況なら、たぶん本来は unapply や unapplySeq でのマッチングも許されてしかるべきなんだろうなあ。 単に現状はコンパイラ (かどうか知らんけど) がバグってるってだけかねえ。

% [clip] 赤城農相の事務所、別の並行宇宙に存在─超時空活動に利用 (bogusnews)

最近は、なんだかよくわからないネタが多かったんだけど、久々にツボに入るネタ。 超時空政治家ワロス。

ボックスの中からは「にゃーにゃー」と鳴き声が聞こえ、

鳴き声聞こえたらシュレディンガーの猫じゃないじゃんw つーか、このペンダントがどうのこうのって、なんか元ネタがあるのか?

% [Scala] Scala 豆知識 (同値判定と同一判定)

Scala では同値判定 (structural equality) は = = (反対は !=) で、同一判定 (physical equality) は eq (反対は ne) である。

scala> val a = (1,2)
a: (Int, Int) = (1,2)

scala> val b = (1,2)
b: (Int, Int) = (1,2)

scala> a == b
unnamed0: Boolean = true

scala> a eq b
unnamed1: Boolean = false

scala> a eq a
unnamed2: Boolean = true

そうして、Java と大変仲の良い言語であるはずの Scala を使えば使うほど Java のコードが書けなくなっていく、そんな日々。 まあ、= = の代わりに equals を使うことも一応可能なので、少しだけなら踏んばれるかもしれない。

って言うか、幸か不幸か、現状わしには Java でコードを書く必要が無いので、もう Scala だけあれば良いや。 でも、Scala にはファイル操作のためのモジュールとかが存在しないので、そういうことやろうとすると、Java のリファレンス読まないとやってられんのだが。


2007-07-09 [長年日記]

% [雑談] 誰か、関数型言語脳に冒された人間のために有効な、ユニットテストの書き方を教えてください

世の中のユニットテストフレームワークってさ、関数型脳に厳しいよね。 だって、テストのコードを抽象化すればするほど、どこで失敗してるのか判別できなくなるんだもの(泣

でもさ、やっぱり同じようなコードが何度も何度も何度も何度も出てくると、どうしたってひとまとめにしたくなるじゃん。 でもそうするとテストの結果が把握しにくくなる。 でも重複したコードを放っとくと、やっぱり気持ち悪い。 でもそうすると結果が……(以下無限ループ)

% [雑談][Ruby] until とか unless って直感的ですか?

よく Ruby では if not ではなく unless と書こう……みたいな主張を聞く気がするんだけど、正直わしとしてはどうにも unless やら until やらに馴染めない。

特に and や or が絡んでくると、もういけない。 っていうか、and や or が絡んだ条件を unless 使ってまともに書けた試しがない。 もしかして、そういう条件のときは unless 使うのが間違ってる?という気もするけど、それならもう if not で良いじゃないの。 きっとゴルファーな人とかも、文字数違わないからどっちでも良いって言うよ (ってか、むしろ if ! の方が短いとか言いそう)。 や、while not より until の方が短かいのは確かだけど。

まあ、そんなわけで、わしには unless や until の存在意義が理解できないんだけど、実際何であるんだろうね。 個人的には、他人に読ませるコード書くときとかに、unless 使った方が良いんだろうか?などと無駄に葛藤を覚えてしまうので、こんなもん無い方が幸せなんだけど。

……こういうこと思うわしってオールドタイプなのかなあ。

% [Ruby] Ruby 使っててちょっとイラっとすること

一言で言うと、ファイルの命名規則が気に食わない。

irb(main):001:0> require 'pathname'
=> true
irb(main):002:0> path = Pathname.new 'hoge'
=> #<Pathname:hoge>
irb(main):003:0> require 'tempfile'
=> true
irb(main):004:0> temp = Tempfile.new 'hoge'
=> #<File:/tmp/hoge.3080.0>
irb(main):005:0> require 'fileutils'
=> true
irb(main):006:0> Fileutils.cd 'hoge'
NameError: uninitialized constant Fileutils
        from (irb):6

ショボーン。 いやまあ、クラス名で憶えろよって話はあるんだけどさ。 でも普通は require を先に書くわけだし、fileUtils とか file_utils とかってなってれば、間違えないと思うんだよなー。

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

Before...

% soutaro [naiveには、 (define-syntax test** (syntax-rules () ((_..]

% shiro [「テストすべき式をメッセージに取り込む」としなかったのは、テストが高階化されたらやっぱり役に立たないからです。__F..]

% jijixi [うーん、やっぱり色々ややこしくて、一筋縄ではいかない問題みたいですねえ。]


2007-07-11 [長年日記]

% [雑談][game] あー、スパロボ OGs やりてーなー

……と思いつつ、買わずにガマンしてるわけだが、零式斬艦刀だけが気がかりなのでプレイ動画とか漁ってみたり。

で、見た。

……うーん、袈裟斬りになってるのは良いよ (つーか真っ直ぐ振り降ろしてるから、袈裟とは言わんのか?なんて言えば良いんだろ)。 GBA 版では、示現流とか言ってるくせして一の太刀が逆袈裟ってどんなだよ、ってツッコミ受けまくりだったわけだから、そこが修正されるのは良い。

でもさー、あの「どこからともなく斬艦刀が飛んでくる」演出が無くなったのは無念でならない。 あれこそが零式の醍醐味だってのに。 しかも、飛んでこなくなったせいで機動力が落ちたのか、射程が 1 になってるしよ。 こんなの零式じゃない!! わしの愛したグルンガスト零式を返せ。 敵の密集地帯に突っ込んで、斬艦刀でバッタバッタと強敵を薙ぎ倒す、あの零式を〜

% [Rails] validates_presence_of で boolean な値をチェックしようとしてドハマりした件

うん、なんつーかね、あれだよね、めちゃくちゃ初心者泣かせだよね。 まあ、たしかにマニュアルをよくよく読めば、書いてあったよ、ちゃんと。 というわけで、boolean 値がブランクじゃないことを保証するには、validates_presence_of は使わずに、

validates_inclusion_of :hoge, :in => [true,false]

と書こう。

……いやね、この件で一時間以上悩んでた気がするんだけど、なんかよくよく考えると、最初にマニュアル読んだときにはこの事に気付いていて、「あーこれは気を付けないとなー」などと考えていたような記憶がかすかにあるのが切なさに拍車をかけるわけよ。 なんつーのか、もー色んな意味でダメすぎる...orz

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

% きむら(K) [>つーか真っ直ぐ振り降ろしてるから、袈裟とは言わんのか? 唐竹割り? #愛国富士山返しとか]

% jijixi [唐竹割りはちょっと思ったんですけど、ググってもそれらしいのって出てこないんですよね。 > 愛国(ry ちょwそれは..]


2007-07-12 [長年日記]

% [Scala] (co|contra|in)variant

Journal In Time を読んでて。

わしの知る限り、こういうことを一番マジメに考えてる言語って Scala だよなーと思った。 Scala では基本は invariant で、必要に応じて covariant や contravariant な定義も可能なんだけど、そういう場合もコンパイル時にがっつり型検査されて、メンバの型が条件を満たしていないクラスは存在し得ない。 ちなみに covariant とかが何物か全然知らない頃に悩んだ件のまとめ → 2006-04-14#p3

……って今見ると、なんか最後の例で貼るもの間違ってるな。何だこりゃ。 あー、確かこの二つの失敗例に続けて、成功例を貼るつもりだったんだっけか?

たぶん貼りたかったのは、こういうの↓のはず。

scala> class Bar[-T] { def f[U<:T](e:U) = Console.println(e) }
defined class Bar

二つ目の例も、なぜか T 型を返そうとせずに、U 型で返せば問題無いんだよね。 (↓の下側の例は返り値の型を指定していないので、型推論によって U と見做されているはず)

scala> class Bar[-T] { def f[U<:T](e:U):U = e }
defined class Bar

scala> class Bar[-T] { def f[U<:T](e:U) = e }
defined class Bar

% [Rails][vim] 文字コードで痛い目に遭う

まあなんつーの? Rails に自動生成されたファイルって日本語含まれてないよね。当たり前だけど。 んで、そういうファイルを開くとさ、わしの vim の設定だと fileencoding は iso-2022-jp になっちゃうのよ。 なんでかっつーと、fileencodings の頭が iso-2022-jp だからね。 iso-2022-jp なファイルを読む可能性があるなら、これは仕方が無いわけ。

でだ、そういう状態の場合、そこに新たに日本語を書き込んで何も考えずに保存すると、当然それは iso-2022-jp で保存されるわけだ。 そうすると、まあ色々とエラい目に遭う。どんだけ色々かっつーと、それはもう様々な領域に渡ってだ(泣

紳士的な解決法としては、常にファイルの先頭にモードラインを書いてやることだろう。 こんな↓感じで。

# vim:fenc=utf-8

でもさ、こんなの忘れるじゃん。しかもめんどくさいし。 そんな感じで、どうしたもんかなーと考えたり調べたりした結果、このページに rails.vim が有効なときだけ autocmd を実行する方法が書いてあったので、そいつを利用させてもらって ~/.vimrc に、

au User Rails* setlocal fileencoding=utf-8

と書いてやることで幸せになった。

そういや、環境変数 RUBYOPT に '-Ke' とか設定してたりしてもハマれるね (まあ、そんなもん設定しとくなよ、って話もあるけど)。 初めて rails コマンド使ったときは何事かと思ったよ。

% [独り言] なかなか思うようには進まないなあ

うーん、いくら色々慣れてないにしても、一週間あればそれなりに良いとこ出来てくるだろう……と思ってたんだけど、なんかこの調子だとまだまだかかりそうだなあ。 深刻なハマりに陥いったり、サボりまくったり……ってことは無いんで、普通に順調に進んでるとは思うんだけど、イマイチ進んでる気がしない。

そもそもそんなもんなのか、わしには向いてないせいで作業効率が悪いのか、よくわからんなあ……

% [clip][Haskell] The Evolution of a Haskell Programmer

2ch の Haskell スレより。 The Evolution of a Programmer の Haskell 版。 ML な人は、やっぱ Continuation-passing Haskell programmer かね?

raised RABBITS in early years, then moved to New Jersey

…って SML のこと言ってる気がするんだけど、RABBITS って何だろ。

Interpretive Haskell programmer 以降が長すぎ(笑)。 んで、最後の Ph.D. Haskell programmer → Post-doc Haskell programmer → Tenured professor って流れが秀逸。

% [clip] variable numbers (Garbage Collection)

via L'eclat des jours.

良いなあ、こういうの好きだなあ。 以下は、わしの「ある日」。

月と地球の距離は約38万km、あなたの身長の2億556万倍。

でも、この距離は一定ではありません。

実は、月は1年間に3.8cmの割合で地球から遠ざかっています。

ということは、あなたが生まれてから今までの間に、

地球と月の距離は132.7cmほど遠くなった、ということになります。

そして、その距離がちょうどあなたの身長と同じだけ離れるのは、

今から、約14年後の2021年10月25日頃のことです。

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

Before...

% みずしま [たぶんGuy Steele Jr.が作ったSchemeコンパイラRABBITのこと なのではないかと思います。 h..]

% みずしま [概要をざっと眺めるなら、さくらばさんのJava in the Boxが いいのではないかと思います。 http:/..]

% jijixi [どうもです。 ひまを見て読んでみたいと思います。]


2007-07-13 [長年日記]

% [Java][Scala] Java の variance notation

みずしまさんが件の記事にツッコミを入れてたので眺めてみたり。

なるほど、これはこれでおもしろい。 Scala の場合、covariant/contravariant はクラスの定義時に決まっていなきゃならないのに対して、Java の場合は、使う時にそれを決められるんだね。

まあ、一つのクラスで covariant だったり contravariant だったりするってのが嬉しいかどうかは微妙な気がするけど、Java の方が手軽な気はする。 つーか、Scala でいろいろおもちゃを書いてるときに covariant なクラスを作ろうとして、ひどい目に遭ったことがあるし variance 関係は怖いから、あんまり近寄りたくなかったり(苦笑


2007-07-16 [長年日記]

% [Rails] ActionMailer + iso-2022-jp + Base64

もうこのご時世じゃ、UTF-8 + Quoted Printable でも良いんじゃネ? ……と思わなくもないんだけども、まあそれでも日本人相手にその組み合わせでメールを投げつけるには勇気がいるのも事実。

irb(main):001:0> s = 'ほげ'
=> "\244\333\244\262"
irb(main):002:0> NKF.nkf('-j',s)
=> "\e$B$[$2\e(B"
irb(main):003:0> NKF.nkf('-w -MQ',s)
=> "=E3=81=BB=E3=81=92"

確かに無駄に長いし。 一見、1.5 倍くらいの違いに見えるけど、実際は iso-2022-jp の方はエスケープが入ってるんで、

irb(main):004:0> NKF.nkf('-j',s).length
=> 10
irb(main):005:0> NKF.nkf('-w -MQ',s).length
=> 18

むしろ二倍近い。

そんな感じで、ActionMailer で iso-2022-jp + Base64 なメールを送りたい場合、なんかそういうことするためのプラグインもあるみたいだけど、とりあえずシングルパートなやつなら、わざわざそんなもん入れなくてもわりと簡単に行ける。 行けるんだけど、微妙にハマりポイントもあるのでメモ。

例えば、こういう↓のがあったとしたら、

class Hoge < ActionMailer::Base
  def hoge(sent_at = Time.now)
    @subject = 'ほげ'
    @body = {:hoge => 'ほげ'}
    # ...以下略
  end
end

これをこんな感じに変えてやれば良い。

require 'kconv'
class Hoge < ActionMailer::Base
  @@default_charset = 'iso-2022-jp'
  def hoge(sent_at = Time.now)
    @subject = "=?iso-2022-jp?B?#{NKF.nkf('-j -MB','ほげ')}?="
    @body = render_message('hoge',{:hoge => 'ほげ'}).tojis
    # ...以下略
  end
end

要するに Hoge#create! メソッドが呼ばれる時点で (この例で行けば Hoge.create_hoge を呼んだときとか)、@body が文字列になっていれば、そこには何も手を付けないし、@subject とか @from とかのヘッダもエンコード済みならそのまま使われるので、これで良い。 良いんだけど、create_hoge で返ってくる TMail::Mail クラスのインスタンスに多少ワナがあって、

m = Hoge.create_hoge
m.body #=> ???

この時の m.body が返す値がなぜか UTF-8 な文字列だったりする。 どうも ActionMailer での拡張のようなんだけど (メールの受信に対応した関係かね?)、body メソッドが自動的にデコードと文字コードの変換をするようになっているのであった。 てことで、実際に送られる文字列を Mail のインスタンスから取り出すには、quoted_body メソッドを使う。

m.quoted_body #=> iso-2022-jp な文字列 (自分で @body に設定した文字列)

まあ、ちょっと変わったことやろうとしたりするんじゃなければ、便利は便利なのかもしれないが、body メソッドでは生データが返ってきてくれた方が直感的じゃないのかねえ……


2007-07-19 [長年日記]

% [独り言] あー進まねー

いや、進んではいる、進んではいるんだけど、とにもかくにも進み方がノロい。

それもこれも、わしがモノを知らなすぎるせいで、何かちょっと進めるたびに想像と違うことが起きて、原因を調べるための時間を食われるから。 ほんと、勉強不足すぎだ...orz

% [Rails] Rails レシピ

費している時間のわりには成果が芳しくなくて、ちょっとモチベーション下がり気味なので、本屋に行って Rails の本をあれこれ物色してみた。 なんつーか、英語のドキュメント読むのにも疲れたし、Rails 関係のソースコードを読むのも疲れるので、何か日本語で読みたいと思ったわけよ。 eval とか method_missing 使いまくった Ruby のコードは、読むには疲れすぎるよね(苦笑

そんなこんなで、近所で一番デカい本屋に行ってみたところ、思ったより種類があって (5 冊くらい。 Amazon とかで検索すると、もっとあるみたいだが)、「そういう時代なんだなー」などと変な感慨を覚えてみたりして。 で、全部をざっと眺めてみた感じ、ほとんどは「これから始める」人向けっぽくて、そこはもう乗り切った (つもり) んで、その先が欲しいんだよ……と考えると、結局 Rails レシピ がちょうど良さそうだったんで、思い切って購入。

とりあえず、目次だけでも読んで、どんな項目があるか把握しておくと、いざってときに助かりそうな予感。 まあ、できれば目次だけじゃなく、中身も読んじゃえば良いんだけども……

% [Rails] migration の意味がようやくわかった

わかってしまうと、SQL の本引っぱり出してきたりとかして、一生懸命テーブルの設定とかやってたのは何だったんだと思うな。

例えばモデルを作るときに、こんな↓感じで generator を使うと、

% ./script/generate model Cat name:string age:integer
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/cat.rb
      create  test/unit/cat_test.rb
      create  test/fixtures/cats.yml
      exists  db/migrate
      create  db/migrate/001_create_cats.rb
% cat db/migrate/001_create_cats.rb
class CreateCats < ActiveRecord::Migration
  def self.up
    create_table :cats do |t|
      t.column :name, :string
      t.column :age, :integer
    end
  end

  def self.down
    drop_table :cats
  end
end

こんな感じのファイルが生成されて、rake db:migrate を実行すると、この通りにテーブルが作成される。 ここまでは、まあわかってた。 けど、これをちょっぴり修正したいときなんかにどうすれば良いのかがわからなくて、今まではこのファイル自体をいじった後、一旦テーブルを手動で消して作成し直したり、直接 MySQL のコンソールからテーブルの内容をいじったりしてたのであった。 ……今考えるとアホみたいだ(苦笑

そもそも 001_ とかの通し番号が何を意味してるのかがわかってなかったんだけど、これは要するにバージョン番号である。 んで、rake db:migrate でこの 001_ なんちゃらが実行されると、データベース上の schema_info というテーブルにバージョン番号として 1 が登録されて、以降、この 001_ なんちゃらは実行されなくなる。 次回以降は、このバージョン番号より大きな通し番号が振られているファイルがあれば、順次実行される寸法。

そういうわけで、例えば上の例の cats テーブルに color という属性を付け足したい場合は、新たに migration 用ファイルを作って追加の処理を書いてやれば良い。

% ./script/generate migration add_color
      exists  db/migrate
      create  db/migrate/002_add_color.rb

まず、雛形を作る↑。 別に自分で一から書いても良いんだろうけど、それはそれでバカらしいので、generator を使った方が良い。 んで、生成されたファイルを以下のように修正して、rake db:migrate してやれば良い。

% cat db/migrate/002_add_color.rb
class AddColor < ActiveRecord::Migration
  def self.up
    add_column :cats, :color, :string
  end

  def self.down
    remove_column :cats, :color
  end
end

self.up を書くのは当然だけど、self.down もバージョンダウンしたいときに必要なので、なるべくちゃんと書いといた方が良いだろう。 特定のバージョンの状態にしたい時には rake db:migrate VERSION=1 のようにバージョンを指定して rake を実行すれば良い。


2007-07-20 [長年日記]

% [Ruby] 後置 if の軽いワナ

や、まあ、使い道にもよるんだけど、個人的には return とか raise とかの、もし if が真だったらそれ以下の部分は処理されないようなシチュエーションでしか使わない方が良いと思った。 つーか、わしがヘボいだけってのもあるんだけど、↓こんなコード書いてて、結果が変だってことに 1 時間近く悩んだわけ(苦笑

def hoge
  msg = 'hoge'
  msg << 'fuga' if ...
  msg << 'piyo' if ...
end

意図としては、'hoge' をベースに何らかの条件に応じて 'fuga' や 'piyo' を加えた文字列を得たいということなんだけど、これではうまく行かない。 要は 'piyo' を足してるとこの if が偽だった場合、msg ではなく nil が返るので、破綻しているということね。 だから正しくは最後にちゃんと msg を返すように書かないといけない。

def hoge
  msg = 'hoge'
  msg << 'fuga' if ...
  msg << 'piyo' if ...
  msg
end

まあ、当たり前っちゃー当たり前なんだけど、後置 if だとどうしても最後の msg << 'piyo' が返り値のように見えちゃうわけよ。 で、ついうっかり最後の msg を書き忘れて、そのまま……という。 しかも困ったことにテストデータが適当だと、たまたまうまく行く例もあるので ('piyo' のところの if が真なら、ちゃんと動いてるように見える) さらに混乱するという。

もともとこの書き方は気に入らなくて、後でちゃんと書き直そうと思いつつやっつけで書いたせいもあるんだけど、ともあれ、値を返すようなときに後置 if 使うのは止めておこうと心に決めた出来事であった。 かと言って、三項演算子は好きじゃないし、普通の if を一行で書くと冗長なんだよなー。

% [雑談][Erlang] Erlang のせいで、無駄なカンマが気になるようになってしまった件

すんごい気になる。 例えば Ruby でこんな↓の書くと、

['hoge',
 'fuga',
 'piyo',
]

'piyo' の後のカンマがすごく気になる。消したい。 でも、有っても無くても挙動が同じなら消すべきではないと思う。 現に今までは当たり前のように、そうしてきた。

でももう、Erlang のせいで気になって気になってしょうがない (注:Erlang ではこういう書き方は許されない)。 こういうコードが視界に入ってると、どうしてもその余分なカンマにちらちらと目を奪われてしまって、集中できない。

いっそのこと、素直に余分なカンマは消す方向でやっちゃった方が精神的にすっきりするのかなあ……

% [独り言] 良い意味で予想に反することもある

簡単に済むと思ってたことが、思ったよりも面倒で時間がかかることもあれば、逆に面倒で時間がかかりそうだと思ってたことが、案外あっさり済んでしまって拍子抜けするってこともある。

そういう良い意味での想定外があると、何となく幸せを感じてしまうのは小市民すぎるだろうか?

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

Before...

% jijixi [OCaml ユーザ的にも同様です(笑 最近ようやくすんなり頭を切り替えられるようになってきました。]

% H.I. [つまり、 ・関数型に書きたいとこでは後置ifは使わない、 ・後置if使うといいとこならちゃんとreturn書く、 で..]

% jijixi [そんなところでしょうね。 やっぱ、関数的な書き方と後置 if は相性が悪い感じがします。]


2007-07-22 [長年日記]

% [clip][雑談] 視野の問題 (L'eclat des jours)

内容に関してはどうでも良くて。(と言うか、この手の話題は問題領域が広すぎて、議論が発散するばかりで一向に実りが無いというイメージがある)

もう1人の緑茶さん

…にコーヒー吹いた(笑)。 や、単に名前から (le the vert とはフランス語で the green tea のことらしい) そう呼んでるだけだと思うんだけど、なんとなくこう書かれると「あれ?芸風似てるかも?」と思えてくるから不思議だ。

% [独り言] ようやく終わりが見えた

昨日、これまでで一番のハマりに陥いってしまって、これはヤバいと思ったんだけど、ふて寝してぐっすり寝たら、今日になってふとひらめいたんで、やってみたら案外簡単に解決してしまい、やっぱり頭が煮詰まってるときは何をやってもダメなんだなーと思ったり。

昨日、半日「ムキーッ」てなってたのは何だったんだろな(苦笑

ともあれ、もう少しだ。がんばろう。


2007-07-24 [長年日記]

% [clip][雑談] 何も思いつかないときに ls を打たないでいられる人がどれくらいいるだろうか (いやいない) (青木日記)

激しく同意(笑

まあ、わしの場合、ls じゃなく lf だが (alias lf='ls -F')。 あと df もあるなあ。 他にも who とか (打ちやすい配置だから好き)。

% [独り言] ようやく一区切り

あとは野となれ山となれ。 明日は明日の風が吹く。 風が吹くと桶屋がもうかる。

……脱線してしまった。

ともあれ、最近常に頭を占めていた事柄から一応解放されたので、今日は久々に精神的なリラックスが得られそう。


2007-07-26 [長年日記]

% [game] 久々に新作ゲームを買った

と言っても、これだが。

よくもまあ、こんな変態ハードを使ったゲームを、ここまでの再現度で移植しやがりましたね。 グッジョブと言う他ありません。

あと、基本的にテクスチャ貼り替えただけのネオクラシックモードが、最近のゲームにしか見えないのは色んな意味でどうかと思った。

他には、用意されてるリプレイデータがあんまり上手くなくて、「なんだこりゃ?」と思ったんだけど、最終面をエネルギー切れギリギリでクリアする辺り、実は計算されたデータなのかもと思ったり。

ところで、この手のシリーズでファンタジーゾーンはいつ出ますか? 以前出たアレもまあ悪くはなかったが、どうせなら完全移植でスーパーリプレイ付きなのが欲しいよ。 あと、マスターシステム用の2とかも入れてさ。

そういえば、ペペログゥのためにコレも買おうと思いつつ忘れてるな。 まあいずれ。

% [独り言] 後悔先に立たずとは言うものの

終わってから、「ああしときゃ良かった。こうしときゃ良かった。」と色々浮かんでくるのは、何とも悔しいものだなあ。 どうして終わる前に思い付かないのか。

まあ、終わる前に思い付いても、「今さらそんな事言ったら、一からやり直しじゃん」みたいな話もあったりするから、なんでもかんでも思い付けば良いってわけでも無いんだが……


2007-07-28 [長年日記]

% [Scala] 2.6.0-RC1

出たよ。 さっそく試す。

まず、念願の Structural sub-typing.

scala> def f(x : { def hoge():unit }) { x.hoge }
f: (AnyRef{def hoge(): unit})Unit

結局、仮引数の型指定は強制されるけど、まあ元々 Scala はそういう言語だから仕方ないか。 ここで、引数 x に指定している型は『引数無しで unit を返す hoge というメソッド』を持っているクラスであれば何でも可という意味。


scala> class Hoge {
     |   def hoge():unit = println("hoge")
     | }
defined class Hoge

scala> class Fuga {
     |   def hoge():unit = println("fuga")
     | }
defined class Fuga

scala> class Piyo {
     |   def hoge():String = "piyo"
     | }
defined class Piyo

scala> f(new Hoge)
hoge

scala> f(new Fuga)
fuga

scala> f(new Piyo)
<console>:6: error: type mismatch;
 found   : Piyo
 required: AnyRef{def hoge(): unit}
  val res2 = f(new Piyo)
               ^

むふふ。 わしは静的型付け言語が好きだけど、ダックタイピングも好きなので、この機能は大好きだ。

次に遅延評価。 これは元々、無引数のブロックが存在したので、同様のことをするのは難しくなかったが、結果をキャッシュすることまで考えると結構冗長だったので、そこを勝手にやってくれるという意味で意義があると思う。

scala> lazy val v = {println("hoge"); 1}
hoge
v: Int = 1

scala> v
res3: Int = 1

一度評価した後は、ちゃんと結果をキャッシュして無駄な計算はしない。 なんか全然遅延評価してないように見えるのは、対話環境が値を表示するために評価しちゃってるせいなはずだから、あんまり気にしないように。

最後に Existential types とか言うの。 ちょっと聞いたことないものだけど、を見る限り、既存の総称型から型パラメータの範囲を制限した新たな型を作る仕組み…なのかな。

scala> type IntList = List[T] forSome { type T <: Int }
defined type alias IntList

scala> def f(x:IntList) = println(x)
f: (IntList)Unit

scala> f(List(1,2,3))
List(1, 2, 3)

scala> f(List(1.0,2.0,3.0))
<console>:5: error: type mismatch;
 found   : List[Double]
 required: IntList
  val res1 = f(List(1.0,2.0,3.0))
                   ^

こっちの書き方は何となくわかるけど、もう一つの val を使った方の定義がよくわからん。 や、意味はわからんでもないけど、それをどう使ったら良いのか?ってのがさっぱり。 とりあえず今後の課題ということで。

% [clip] 【高校野球】“振り逃げ3ランホームラン”で横浜高校がまさかの予選敗退 (痛いニュース)

これは痛々しい。 横浜の選手にとってはトラウマものだな。 特にキャッチャーとか、もう一生野球する気になれないんじゃないの?

% [雑談] 首を振って直球を投げるサイン

今朝の新聞に、昨日のプロ野球で巨人の阿部が「首を振るサイン」を使ったって書いてあって、コーヒー吹いた。 適当に探した参考リンク→内海完封!ブッ飛び2安打10K (スポーツ報知)

それ、なんておお振り?

……と思ったのは、わしだけではあるまい。

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

Before...

% jijixi [審判のコール云々より前に、あのシチュエーションなら普通にバッターにタッチするように練習するんじゃないかと思うんですけ..]

% きむら(元野球少年) [あー確かに「骨髄反射」(某所で見かけて受けた)で覚えこませるものですね。 ただ、ハーフバウンドを前にこぼしたというも..]

% jijixi [> えー、でも打点(RBI)つかないですよね? そりゃそうだ、実際『打ってない』ですもんね(笑]


2007-07-30 [長年日記]

% [雑談] ある点で調子が良いからといって、全ての点で調子が良いというわけではない

たま〜に朝型人間に変身することもあるけど、基本的にはわしは夜型人間であって、つまるところ夜の方が頭の回転が快調なのである。 そんなわけで、お仕事なぞは夜にやった方が効率が良いんだが、どうも余計なところまで回転が良くなるのか、メールとかブログのコメントとかを書くと書かんで良いことまで、ついつい書いてしまったりして後でヘコむことが結構ある。 (その点、自分の日記は良いな。後で直せるし)

ということで、どうしても急いで返事を書かなきゃならない場合はともかく、そうでない場合はメールは午前中くらいの脳がまったりとした回転をしている頃合いに書くのが良いのだろうなあ、などと思った次第。 でも、たまに朝型人間だったりすると、そのときは逆に午前中は危ないわけで、なかなかその辺悩ましいのである。

つーか、ここ一ヶ月くらいの間に書いたメールって、全部回転速いときに書いてる気がしてダメダメだ (まあ、回転が速いってことは行動的だってことなんで、ほっとくとどうしてもそうなっちゃうんだが)。 そもそも、わしの『回転が速い状態』って基本的に内に向かってると言うか、一人で何か作業するのには適してるけど、誰かとコミュニケーションを取るのには適さない状態なんだよな。 何かこう、頭の中で考えてることが、言葉だとか文章というボトルネック部分に詰まってしまって、ぐだぐだになるというか、脳と口や手がうまく律速できないというか。

かと言って、うかつに脳の方を無理にスローダウンさせると、簡単には元に戻せなくなるから本来やるべきことが全部ダメになってショボーンという。 この辺の切り替えがうまくできる人って、うらやましいなあ。


2007-07-31 [長年日記]

% [clip] 襲  っ  て  く  る  突  然  の  腹  痛 (日刊スレッドガイド)

誰もが一度は経験する危機。おもしろすぎる。

わしは、清掃中→清掃中→満員→ギリギリセーフ、という綱渡りをした経験あり。 つーか、比較的近いトイレを同時に清掃中にするのはヤメレ。


トップ 最新 追記

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

RSS はこちら

jijixi at azito.com