トップ «前の日(11-10) 最新 次の日(11-12)» 追記

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

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|

2003-11-11 まだまだゼルダ。

% 船旅を楽しむ。

そんな精神的な余裕が出てきた今日この頃。ゼルダの話だけどね。

んで、海皇紀をこよなく愛しているわしとしては、安易に風の唄で風向きを変えずに、一生懸命タッキングやらウェアリングやらを駆使して風上に向かって進んでみたりして遊んでるわけです。こいつの切り上がり性能は並じゃない、とか言って(笑

風上に進む速さを競うレースとかあると楽しいのに・・・


2004-11-11 OpenOffice.org のエキスパートになってしまいそうだ

% [雑談] 全米シェア第3位!最後の大物ゲートウェイがついに日本上陸!

ツクモのメールニュースに書かれた文句である。まるで『初めて』のことのような言い様に、苦笑を隠せないわしであった。じゃあ、今わしの足元に鎮座まします牛マーク入りの Pentium2/400MHz なマシンは一体何なのかと(笑

% [雑談] 小改造中

つか、ただプラグインを有効にしてみたりしてるだけだけど。

% [雑談] もしかしたら関連するかもしれないページ

random_google.rb というプラグイン。ほんとは何らかの形態素解析ライブラリを通してキーワードを拾わせるものみたいだが、あえてそれを使わないデフォルトの動作をさせてます。なので、『もしかしたら』も何も、『ほとんど関連しない』ページを検索されることでしょう(笑

ま、それが楽しいってことで。

% [雑談] あれ…思ったより多い……

まあ、あんまり裕福じゃないんで、多くもらえるに越したことないんだけど……良いのかなあ、これで。そういや、この前つぶやいた件はいつの間にか直ってたなあ。

・・・全然わけわかんないよね(苦笑)。良いのよ、わしの日記なんだから、わしさえわかれば。

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

% ああああ [誰か日本ゲートウェイのカスタマーセンターの電話番号教えてつながらへん(T_T)]

% jijixi [だからって、こんなところでそれを訴えられてもなあ(苦笑 とりあえず、この辺↓じゃダメ?ダメなら、あとは知らんですよ。..]


2005-11-11

% [OCaml] F# 体験記

ちまちまいじってみた。オブジェクト指向絡み以外は普通に Caml だなって感じだね。 逆にオブジェクト関係は微妙に不満もある。 文法の違いは良いとしても、メソッドを関数として取り出せないのが残念。 OCaml だと、

# class hoge =
  object
    val v = "hoge"
    method get () = v
  end;;
class hoge : object val v : string method get : unit -> string end

# let o = new hoge;;
val o : hoge = <obj>

# o#get;;
- : unit -> string = <fun>

こんな風にインスタンスメソッドを関数として取り出せる。当然、カリー化もできる。

# class fuga =                               
  object (self)                              
    method p s1 s2 = print_endline (s1 ^ s2)
    method hello = self#p "hello "
    method hello_world = self#hello "world"
  end;;
class fuga :
  object
    method hello : string -> unit
    method hello_world : unit
    method p : string -> string -> unit
  end

# let o = new fuga;;
val o : fuga = <obj>

# o#hello_world;;   
hello world
- : unit = ()

# let f = o#p "This is a " in
  f "pen.";;
This is a pen.
- : unit = ()

この辺、通常の仕様と一貫性があって、とても好ましい。 んで F# の場合、カリー化はできるんだがメソッドそのものを取り出すことができないのが一貫性に欠ける気がする。

> type Hoge =                                  
  class                                        
    new() = {}          
    member self.p s1 s2 = print_endline (s1 ^ s2)
    member self.hello = self.p "hello "          
    member self.hello_world = self.hello "world" 
  end;;
val Hoge.hello.get.1 : Hoge -> unit -> string -> unit
val Hoge.hello_world.get.1 : Hoge -> unit -> unit
val Hoge.new.0 : unit -> Hoge
val Hoge.p.2 : Hoge -> string -> string -> unit
type Hoge

> let o = new Hoge();;
val o : Hoge

> o.hello_world;;
hello world
val it = null
val it : unit

> let f = o.p "This is a " in
  f "pen.";;
This is a pen.
val it = null
val it : unit

> o.p;;
toplevel(2,0): error: Syntax expr.id is may only be used with record labels, properties and fields.
stopped due to error

まあ、些細なことかもしれないが、わしは広範囲に及ぶ識別子は長い名前を付けておいて、使うときにはローカルな短い名前を付けて使う…ってなやり方を好むもんで、どうもね。

% [OCaml] 続 F# のモジュール

もう少し詳しい説明を発見。 ファイルの先頭でモジュール名を宣言しない場合は、OCaml と同様のルールでモジュール化される模様。

% cat sub.fs
module Mylib.Mymod
let p s = print_endline s

% cat main.fs
let _ = Mylib.Mymod.p "Hello World"

% fsc -o a.exe sub.fs main.fs
% ./a.exe
Hello World
% cat sub2.fs
let p s = print_endline s

% cat main2.fs
let _ = Sub2.p "Hello World"

% fsc -o a.exe sub2.fs main2.fs
% ./a.exe
Hello World

それはそうと、なんか ocamlc の -c オプションに相当するものが無い。 ……つーか、そもそもファイルごとのオブジェクトファイルを生成しないし、常にソースから実行ファイルを作るしか無いみたいね。 ライブラリを作りたいときはどうすんだ?と思ったが、-a オプションで DLL を作るのがお作法らしい。

% fsc -a sub.fs
% fsc sub.dll main.fs
% ./main.exe
Hello World

これはこれでスマートではあるな。

% [OCaml] F# の強み

なんだかんだ言って、.NET Framework の API が使えるのはかなり強力だよな。 GUI 以外の部分でも便利なものはいっぱいあるし。

レコード型にメソッドを追加した Members は意味あるのかわからんけど。 VB.NET だと構造体とクラスではメモリの使い方が違うとかなんとかって話があったが、これもそういう類いだろうかね。

% [OCaml] F# on Mono

F# の配布物の中身をごそごそあさってみると、install-fsharp.sh ってファイルがあって、その中にはこんなことが書いてある。

  1. This script is for use with CLIs on Unix, e.g. Mono

ちゃんと動くのかはわからんが、Mono で動かすことも想定されてはいるようだ。 あとで試してみよう。 つーか、Mac に Mono インストールしてあったっけな? インストールするところから始めなきゃダメかも(苦笑

% [OCaml] F# への不満

.NET API が使えることが強烈なアドバンテージになってるのは良いとして、OCaml でできることができないと微妙にストレスが溜まるなあ。

# class hoge =
  object
    method p = print_endline "hoge"
  end;;
class hoge : object method p : unit end

# class fuga =
  object
    method p = print_endline "fuga"
    method dummy = ()
  end;;
class fuga : object method dummy : unit method p : unit end

# let f x = x#p;;
val f : < p : 'a; .. > -> 'a = <fun>

# f (new hoge);;
hoge
- : unit = ()

# f (new fuga);;
fuga
- : unit = ()

こういうの。F# ではできない。

> type Hoge =
  class
    new () = {}
    member self.p = print_endline "hoge"
  end;;
val Hoge.new.0 : unit -> Hoge
val Hoge.p.get.1 : Hoge -> unit -> unit
type Hoge

> type Fuga =
  class
    new () = {}
    member self.p = print_endline "fuga"
  end;;
val Fuga.new.0 : unit -> Fuga
val Fuga.p.get.1 : Fuga -> unit -> unit
type Fuga

> let f x = x.p;;
toplevel(2,10): error: Lookup on object of indeterminate type.
A type annotation may be needed to constrain the type of the object
in order for the lookup to be resolved.
stopped due to error

> let f (x : Hoge) = x.p;;
val f : Hoge -> unit

こういう場合は interface を使わなきゃならないんだろう。 良くも悪くも .NET 色ってことか。

% [OCaml] F# のワナ

カテゴリを OCaml のまま F# の話題を続けるのはどうなのか?という気もするが、まああくまでも OCaml ネタの派生としての F# ネタだということで。

OCaml に比べて微妙に泣ける点を見つけてしまった。

> let h = Hashtbl.create 0;;

toplevel(2,4): error: FS0030: Type inference has inferred the signature
        val h : ('b,'a) Hashtbl.HashTable 
for 'h', but the definition of 'h' involves some computation, which cannot be performed before specific types have been given for the type parameters in the inferred type. Either define 'h' as a simple data term, make it a function, or add a type constraint to instantiate the type parameters.

stopped due to error

がっくり。 ちなみに OCaml だと、

# let h = Hashtbl.create 0;;
val h : ('_a, '_b) Hashtbl.t = <abstr>

こうね。もちろん、こうすれば…

> let h : (string, string) Hashtbl.t = Hashtbl.create 0;;

val h : (string,string) t

…良いわけだけど、なんか納得いかんよな。 ……ところが、ちょっと思いついてこんなんしてみた。

% cat abst_test.fs
let h = Hashtbl.create 0
let _ = Hashtbl.add h "hoge" "fuga"
let _ = print_endline (Hashtbl.find h "hoge")

% fsc abst_test.fs
% ./abst_test.exe
fuga

……な、なんだってぇ!?

まあねえ、これなら実用上は問題ないだろうけど……イマイチ納得いかない。

% [OCaml] F# のワナ、続き

'_a とかの一時的な多相型ってなんて呼べば良いんだっけね。 まあ、名前はこの際どうでも良いんだが。 ともあれ F# では、この一時的な多相値がダメなのかと思ってたんだが、実際には mutable な多相値は軒並みアウツみたいね。 バータリープログラミングの味方、option 型のリファレンスなんかも全滅だ。ババンバン。

> let a = ref None;;

toplevel(2,4): error: FS0030: Type inference has inferred the signature
        val a : 'a Option ref
for 'a', but the definition of 'a' involves some computation,
which cannot be performed before specific types have been given for the type parameters
in the inferred type. Either define 'a' as a simple data term, make it a function,
or add a type constraint to instantiate the type parameters.

stopped due to error
> let a = [| None |];;

toplevel(2,4): error: FS0030: Type inference has inferred the signature
        val a : 'a Option array
for 'a', but the definition of 'a' involves some computation,
which cannot be performed before specific types have been given for the type parameters
in the inferred type. Either define 'a' as a simple data term, make it a function,
or add a type constraint to instantiate the type parameters.

stopped due to error

まあ、さっきの例でもわかるように、後から型推論のヒントが出てくれば大丈夫なわけだけど。 ただ、多分ファイルをまたいじゃうとダメなんだろうなーと思って、念のため


% cat sub.fs
let a = ref None

% cat main.fs
let _ = Sub.a := Some "hoge"
let _ = print_endline (match !Sub.a with Some s -> s)

% fsc -o a.exe sub.fs main.fs

sub.fs(1,4): error: FS0030: Type inference has inferred the signature
        val a : 'a Option ref
for 'a', but the definition of 'a' involves some computation,
which cannot be performed before specific types have been given for the type parameters
in the inferred type. Either define 'a' as a simple data term, make it a function,
or add a type constraint to instantiate the type parameters.

main.fs(1,17): error: FS0001: Type mismatch. Expecting a
        obj Option
but given a
        string Option
.
The type obj does not match the type string

main.fs(2,51): error: FS0001: This expression has type
        obj
but is here used with type
        string

main.fs(2,23): warning: FS0025: Incomplete pattern match.

sub.fs に対して出てるエラーは fsi で出るのと同じ。やっぱりファイルをまたがるとダメ。 それはともかく、main.fs に対して出てるエラーが激しく謎。 参照しようとしてるのは 'a Option のはずなのに、なぜか obj Option なんてものになっている。 なぜ?

ってことで調べてみたところ、こんなのが。 多分、CLR 側の型名が出ちゃってるんだろう。 基本的に 'a と obj は自動的に変換されるものみたいだから、気にする必要は無いと思われる。

多相値が多相値のまま存在できないのは、CLR の制限なのかね。 まあ、ファイル一個で他の言語から利用するアセンブリの要素になりうるのに、『使用される事で型が変化(あるいは確定)し得る値』なんてものがあると迷惑だってことかも知れない。 ともかく、そう言うもんだとわかってれば別にどうってことない制限だから、この件はこんなところで良いだろう。

% [OCaml] F# を Mono で動かす計画(失敗)

動かにゃい。でもせっかくだから、何をどうしてみたのかメモっとく。 環境は、

Mac OS X 10.4.3 / iMac G5
% uname -v
Darwin Kernel Version 8.3.0: Mon Oct  3 20:04:04 PDT 2005;
root:xnu-792.6.22.obj~2/RELEASE_PPC

Mono 1.1.10 (オフィシャルサイトから落としてきた dmg 版)
% mono --version
Mono JIT compiler version 1.1.10, (C) 2002-2005 Novell, Inc and Contributors.
www.mono-project.com
        TLS:           normal
        GC:            Included Boehm (with typed GC)
        SIGSEGV      : normal

FSharp 1.1.3.2

とりあえず FSharp に付いてきた install-fsharp.sh の中身はインチキなので(ファイル名の変更に追随できてないっぽい)、ともかくそれらしい dll を登録。

% foreach i (bin/*.dll)
sudo gacutil -i $i
end
Password:
FSharp.Compiler installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
Failure adding assembly to the cache: The file specified is not a valid assembly.
Failure adding assembly to the cache: The file specified is not a valid assembly.
Failure adding assembly to the cache: Attempt to install an assembly without a strong name.
Failure adding assembly to the cache: Attempt to install an assembly without a strong name.
fslib installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
fslib10 installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
fslib10ntc installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
mllib installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
mllib10 installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
mllib10ntc installed into the gac (/Library/Frameworks/Mono.framework/Versions/1.1.10/lib/mono/gac)
Failure adding assembly to the cache: The file specified is not a valid assembly.

んで、実行。

% mono -v bin/fsi.exe
Method (wrapper managed-to-native) System.Object:__icall_wrapper_mono_thread_interruption_checkpoint () emitted at 0x4b03b8 to 0x4b0478 [fsi.exe]
Method (wrapper managed-to-native) System.Object:__icall_wrapper_mono_thread_force_interruption_checkpoint () emitted at 0x4b0480 to 0x4b055c [fsi.exe]
Method (wrapper runtime-invoke) System.Object:runtime_invoke_void_string (object,intptr,intptr,intptr) emitted at 0x4b0560 to 0x4b0688 [fsi.exe]
Method System.OutOfMemoryException:.ctor (string) emitted at 0x4b0690 to 0x4b06d0 [fsi.exe]
Method System.SystemException:.ctor (string) emitted at 0x4b0728 to 0x4b0768 [fsi.exe]
Method System.Exception:.ctor (string) emitted at 0x4b0798 to 0x4b07d8 [fsi.exe]
Method System.Exception:set_HResult (int) emitted at 0x4b07e0 to 0x4b0810 [fsi.exe]
Method System.NullReferenceException:.ctor (string) emitted at 0x4b0818 to 0x4b0858 [fsi.exe]
Method System.StackOverflowException:.ctor (string) emitted at 0x4b0860 to 0x4b0890 [fsi.exe]

** ERROR **: file metadata.c: line 1827 (do_mono_metadata_parse_generic_class): assertion failed: ((gclass->context->container = gklass->generic_container) != NULL)
aborting...

うーん…… F# 自体が .NET Framework の 2.0 以上を要求したりするし、Mono が F# に必要な機能を提供できてないってことかねえ。

% [OCaml] Haskellの$(soutaroにっき)

そもそも Haskell の $ ってのがどんなもんだかわからなくてピンと来ない。 ので、Hugs の Prelude.hs を見てみた。

($)            :: (a -> b) -> a -> b
f $ x           = f x

なるほど。 それにしても、Haskell で一般的だと思われる、この思いっきり隙間が空く記法はどうしても好きになれないな。 タブ幅は 8 を推奨とか言われても 3 タブ同盟としては対応に困る(苦笑

ともあれ、せっかくだから OCaml で試してみよう。

# ($);;
Unbound value $

# let ($) f x = f x;;
val ( $ ) : ('a -> 'b) -> 'a -> 'b = <fun>

# let f x = x + 1;;
val f : int -> int = <fun>

# let g y = y + 2;;
val g : int -> int = <fun>

# f g 0;;
This function is applied to too many arguments, maybe you forgot a `;'

# f $ g 0;;
- : int = 3

ほほう。

% [OCaml] メソッド定義のスタイル

OCaml とか F# とか興味ない人には申し訳ないほどの勢いでエントリが続いてるが、なんかよくわかんないけどそういうスイッチが入っちゃってるんで勘弁願いたい。

クラス定義の際に引数無しのメソッドを作る場合には、二種類の書き方がある。 仮引数を書かない場合と、通常の関数宣言のように () を書く場合だ。

# class hoge =
  let p = print_endline in
  object
    val v = p "variable."
    method get = v
    method m1 = p "method 1."
    method m2 () = p "method 2."
  end;;
class hoge :
  object
    val v : unit
    method get : unit
    method m1 : unit
    method m2 : unit -> unit
  end

m1 と m2 の型を比べればわかるとおり、仮引数無しだとメソッドを関数として取り出すことができない。 通常の文法から想像すると m1 は関数ではなく単なる値のような気になるが、実際は単に引数が必要無いだけで、中身はちゃんと呼び出しの都度評価される。

# let o = new hoge;;
variable.
val o : hoge = <obj>

# o#get;;
- : unit = ()

いやあ、こういう実験するとき副作用は便利だなあ。 val v の中身はインスタンス化のときに評価されるので、new したときに variable. と表示されてるね。 その後、get メソッドで中身を取得しても、v の中身はすでに評価済みなのでユニット型が返ってくるだけ。

# o#m1;;
method 1.
- : unit = ()

# o#m2;;
- : unit -> unit = <fun>

# o#m2 ();;
method 2.
- : unit = ()

んで、m1 と m2 の動作の違いはこんな感じ。 この二つをどう使い分けるかなんだけど、わしの場合は単なる変数へのアクセサの場合は引数無しで(上記の get みたいなのね)、引数がいらない関数の場合は仮引数付きにしてる。 要するに、アクセサの場合は純粋に値として使えれば良いわけだから、通常の値と見た目で一貫性があった方が好ましいと思うし、関数扱いの場合も同じように通常の関数と見た目で一貫性があった方が良いんじゃないかと思うわけ。

あと、他に使い分けの指針を考えるとすれば、他のオブジェクト指向言語みたいにメソッドチェーンしたい場合に引数無しを使うってのもあるかな。

# class fuga =
  let p = print_endline in
  object (self)
    method p1 = p "fuga"; self
    method p2 () = p "fuga"; self
  end;;
class fuga : object ('a) method p1 : 'a method p2 : unit -> 'a end

# let o = new fuga;;
val o : fuga = <obj>

# o#p1#p1#p1#p1;;
fuga
fuga
fuga
fuga
- : fuga = <obj>

# o#p2()#p2()#p2()#p2();;
This function is applied to too many arguments, maybe you forgot a `;'

# (((o#p2())#p2())#p2())#p2();;
fuga
fuga
fuga
fuga
- : fuga = <obj>

p2 の方はいかにも冗長だよね。 ただまあ、引数有りなメソッドなら結局はこうなっちゃうわけだから、あんまり気にしても仕方ない気はする。

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

Before...

% _ [みんなには内緒ですよ? >|| #camlp4o;; #require "camlp4.gramlib";; #re..]

% jijixi [おお、なんかスゴイの来た。 camlp4 の勉強は何度も挫折してるんで(苦笑)、使いこなしてる人は尊敬します。 @ ..]

% _ [がーん、向井先生のページで$を使ってはいけない理由がorz]


2006-11-11

% [clip] バイナリアン度チェック

なぜか 80 点とか出てビビる。 実際のところ、ちゃんと答えられたのは半分くらいのもんで、残りは霊感山勘第六感なので全然わしはバイナリアンではないと思います。

って言うか、正直者プレイヤーのために各設問には『わからない』を追加すべきだと思ったり、思わなかったり。


2008-11-11

% [game] R-TYPE FINAL 日記、ほんとワープ面うざい

DELTA の方はどうにか三機種でクリアできたので (KIDS だけど)、FINAL を再開してみたんだがやっぱワープの面がダメすぎる。

画面を凝視しちゃうと間違いなく酔うので、画面の外に焦点を当てつつ何となく見るという戦法でがんばってるが、ボスがまた意地悪くてイヤになる。 自機を吸い寄せる攻撃があって、それに引っ掛かったらスピード上げないと逃げられないんだけど、スピードを上げると画面の歪みが比例して大きくなるので、もうわけがわからない。

単品の攻撃パターンだけでも十分イヤなのに、パターンは 4 種類 (か、さらにもう一つくらい) あってそれらがランダムで繰り出される。 それでも画面の歪みが無ければ何とかなると思うんだけど、歪みのせいで画面をじっくり見てられないからなおさら対処が遅れるんだよな。 で、吸い込みに引っ掛かってしかたなくスピード上げて超ぐにょぐにょになって自分から敵に突っ込んで死亡みたいな。

何回もチャレンジしてやっとのことでボスを倒しても、もうすっかり気力が減少してるしコンティニューの残りも少ないしで、その後はほとんど先に進めない。 せっかく KIDS よりも簡単な BABY レベルができてヌルいわしにも安心と思ったのに、難易度設定以前の問題で攻略を阻まれてるのが悔しすぎるな、ほんと。

% [clip] sm460111 (ファミコン R-TYPE 全面クリア)

腹筋崩壊www

まず一面の BGM がおかしくておかしてw


トップ «前の日(11-10) 最新 次の日(11-12)» 追記

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

RSS はこちら

jijixi at azito.com