yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/06 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
脱線事故のその後
2009/07/10(Fri)21:15:22
 2005年にJR西日本の尼崎線で脱線事故が発生し、100人以上が死亡する大惨事となりました。猛スピードでカーブに進入した列車が線路をはずれ、マンションに突っ込むという未曾有の大事故であり、非常に多数の死傷者数といい、非常に印象の深い事故であることは間違いありません。
 事故の際に運転手が死亡してしまったため事実確認は困難になり、当時は刑事責任を問われる者もいませんでした。JRは当初「置き石」説を持ち出すなど、さも自社以外に原因があるかのような主張を行っており、日勤教育など無茶としか言いようがない懲罰を行っていたり、あまりにも過密すぎるダイヤが事故を誘発したとして、批判を浴びました。また、現場のカーブに対して自動停止装置を設置していなかった点が事故の直接的な原因の1つともされており、その意味でも批判がなされていました。
 また、JRは事故の後の対応でもトラブルを起こしており、遺族との間で問題も発生しています。一方、JR以外で傍若無人な振る舞いを見せる者もおり、例えばマスコミは休日にボウリングをしていた社員を攻撃したり、自分が下手に救助を行ってもお荷物になるのは見えており、公共の利益のために出勤して列車に乗ろうとした出勤・移動中の乗務員を攻撃したり、「社長を出せ」と怒鳴ってみたりと、相手が逆らえない立場と見るや、やりたい放題の行動を繰り返していました。
 そして、今頃になって社長の山崎氏が起訴されました。罪状は業務上過失致死傷で、現場のカーブに自動停止装置を取り付けなかったことが問題であるとされています。山崎氏1人だけが責任を問われたのは、他の幹部は問題のカーブの危険を知らなかったり、装置についての知識がなく、責任を問えそうな人物として氏1人が残ったためのようです。
 法的な面から言えば、この起訴には疑問が否めません。私はそもそもこの種の事故の運転手に罰を科す行為をやめるべきと考えていますが、責を問おうにも運転手は事故で死亡しています。日勤教育や過密ダイヤなどの無茶な企業体質は事故の原因の1つではありますが、日勤教育の存在から直ちに事故を予見するなどといったことは不可能であり、この点で刑事責任を問うのは困難です。したがって、大事故でありながらも刑事責任の追求は難しく、「加害者」の存在しない状態となっていました。今回の山崎氏は、このスケープゴートに選ばれた印象が否定できません。
 装置を設置しなかった行為が業務上過失致死傷に当たるのであれば、これは当然不作為犯となります。不作為犯とは、例えば「死ぬかもしれないと考えつつ、昏睡した被害者を氷点下の野外に放置した」ような場合に適用されるもので、この場合は殺人罪となります。本来なら違法性を生まないはずの「何もしない」行為が逆に罪に問われるのですから、通常より責任を問うのが困難でなければならないのは言うまでもありません。
 検察に自信がないらしいことは、社長のみが起訴された点にも現れています。「自分が取れる限りの何らかの措置を取らなくては、刑法に触れる問題が発生すると考えた」上で「何もしなかった」事実が必要とあっては、それだけの情報や権限、責任を持たない人の責任は追及できません。これを厳密に考えれば、おそらく山崎氏を含めた全員について責任を問うのは困難なはずですが、誰一人として責任なしとするのは難しいため、かろうじて境界線上の山崎氏を狙ったと考えるのが自然です。ただ、装置の設置が事故防止に必要な行為と認識されていたか、それを現場のカーブに設置しなくてはならないと認識できたか、事前にあのような事故の発生が予見できるのか、山崎氏に装置を設置する権限があったか、などのような問題が山積しています。
 私は決してJRを擁護する気はありません。日勤教育に代表される体質は実にひどいものですし、遺族との賠償交渉も後味の悪いものです。しかしながら、今のところ検察が称している理由で不作為を問うのは容易でない印象ですし、公判を維持できるか懸念の声もあるようです。司法にしても、本来なら有罪とはできないところを、世論に押されて有罪判決を下そうものなら問題です。事実、検察は遺族から聴取を行った上で、幹部らの刑事責任を問うことを決定しています。表向きは「起訴は証拠に基づいた判断。遺族の意見でモチベーションが上がり、証拠を固めて起訴にこぎつけた」と主張していますが、事実上は「お伺い」の色彩が強いものでしょう。
 また、裁判で責任のあるなしでもめた末、山崎氏に執行猶予などの判決が下った、あるいは社長辞任で腹を切ったとして「一件落着」となり、そのまま責任や原因がうやむやになってしまう可能性もあり、私はこれを強く危惧しています。
 山崎氏の責任はともかく、JRの日勤教育などの体質が複合的に影響し、事故を招いたことについては異論はないでしょう。JRが事故後に反省したのであればまだしも、遺族を自殺に追い込むなどしている事実からすれば、体質は表向きしか変わっていないと考えるのが自然です。検察は経営者の罪を問うのに躍起になっている印象がありますが、今回の起訴で一応の「経営責任の追求」が行われたとしても、決してJRの体質に影響は与えないでしょう。同じような事故がまた発生するのでは全く意味がありません。今回の起訴に関しては、どうにも検察の意図を測りかねます。一説には「以前の花火事故への処理で批判を浴びたがためのトラウマ」などとも言われていますが、事実なのでしょうか。

 今回はOCamlとF#のオブジェクト関連機能について。F#はOCamlのライブラリを生かせるように作られており、OCaml用に書いたプログラムの一部はそのままF#でも動作したりするのですが、ざっと見比べるだけでも相当に違う部分が見つかります。その1つがオブジェクト指向がらみの部分です。
 .NETでプログラムを書くにあたっては、クラスを作成できなければ話になりません。OCamlの場合は、もともとオブジェクト指向機能を持っていない言語に対してそれを付加したものですので、必ずしもクラスを作成しなくても十分にプログラムは書けますが、.NETはそもそもオブジェクト指向が根本にあるような仕組みとなっています。F#はOCamlがモデルとあって、それでもプログラムが書けないわけではないはずですが、そうなると.NETの長所がかなり失われます。また、どうせF#を使うのであれば、プログラムの主要な流れの部分はC#で作成しつつ、数学的な演算のパーツはF#で書く、などといった使い方もしてみたいものです。
 OCamlにしても、せっかく「Objective-Caml」を使うのですから、オブジェクト指向を使わないのであれば宝の持ち腐れで、それなら最初から「Caml Light」を使用した方が良いでしょう。それに何より、せっかく存在する機能なのですから、使ってみたくなるのは必然です。色々能書きを書いてはみましたが、これらの機能を使ってみたい理由としては、「そのような機能があるから」の一言で十分でしょう。
 F#の仕様は膨大な上に英語で書かれており、とても読みきれそうにありませんので、とにかくクラスを作成し、動きさえすれば良しとしてみます。まずはOCamlから。
class some = object
	method message = print_string "Method"
end;;

new some#message
 クラス名の前にはclassと記述し、イコール記号に続いてobjectと記述、メソッドを宣言する際にはmethodと書くらしいと分かります。オブジェクトはnewで作成し、javadocのようにシャープ記号でメソッドを呼び出しています。
 一方、F#ではこうなります。
type Some () = class
  member this.Message : unit = System.Console.WriteLine "Method"
end;;

let s = new Some ();;
s.Message
 Mono 1.2.6の時期にF#を試してみた時の記憶があり、仕様が変わっている可能性を考えつつ以前に習得した記法を使ってみたところ、しっかり動いてしまいました。
 クラス名の後に空のタプルらしきものがありますが、ここにはコンストラクタの引数を記述するようです。今回はコンストラクタに引数を渡しませんので、()を使っています。これを省略した場合、「コンストラクタが見つからない」旨のエラーが表示されます。MSのドキュメントによれば、この方法は「Primary Constructor」と呼ぶようです。
 なお、F#にはnewを使ったコンストラクタの作成方法もありますが、そちらでコンストラクタを用意した場合には、これを記述する必要はありません(記述しても構わないようですが、初期化されない変数があってはなりません)。その場合には以下のようになります。
type Some = class
  new () = {}
  member this.Message : unit = System.Console.WriteLine "Method"
end;;

let s = new Some ();;
s.Message
 これらの記法にはそれぞれ色々と複雑な規定は存在していますが、これは今回は割愛するとして、上記の場合はどちらでも同様に動作します。
 メソッド名の前にはmemberと記述し、メソッド名でもthis.Messageのようにthis.と記述しています(ただし、必ずしもthisと書く必要はありません。ここで記述した名称が、C#でいうthisにあたる変数名となります)。オーバーロードの関係か、.NETのメソッドとして扱うためか、メソッドの型宣言を省略すると警告が発生しました。また、コンストラクタが引数をとらない場合であっても、インスタンス生成の際には引数として空タプルを指定しなくてはならないようです。メソッドの呼び出しはドット記号で行います。
 次に、クラスがメンバ変数を含む場合を考えます。メンバ変数を直接扱うのは礼儀に反していますので、それを扱うメソッドも一緒に書いてみます。まずはOCamlより。
class some = object(this)
	val mutable x : int = 0
	method get_x : int = x
	method plus_x (v : int) : unit = x <- this#get_x + v
end;;

let s = new some in
	s#plus_x 9; s#plus_x 8; Printf.printf "Total: %d" s#get_x
 単純な足し算のクラスです。
 OCamlにおいては、objectの後に(this)などと変数名を記述可能となっており、この変数はC++やC#でいうthisと類似の機能を持ちます(例によって名前はthisでなくても構いません)。メソッド内部でメンバ変数を使用する際には、単にそのメンバ変数名を記述すれば足りますが、何らかのメソッドの中で自分自身のメソッドを呼び出す必要があるのであれば、この変数から呼び出す必要があります。
 メンバ変数にはmutableと書いておかなければ値が変更できないようで、それなしに<-を使おうとすると「The instance variable (variable name) is not mutable」と文句を言われてしまいます。関数型言語は参照透過的でないものを嫌う傾向にありますので、そこはさすがに関数型です。また、変数には初期値を与えなくてはなりません。メンバ変数への代入は<-を使って行うようです。
 これをF#で書くと、次のようになります。
type Some = class
  val mutable x : int
  new () = {x = 0}
  member this.GetX : int = this.x
  member this.PlusX (v : int) : unit = this.x <- this.GetX + v
end;;

let s = new Some () in
  s.PlusX 9; s.PlusX 8; Printf.printf "Total: %d" s.GetX
 メンバ変数を使う場合であっても、thisを使ってアクセスしています。thisなしでxにアクセスしようとすると、そのような変数はないと言われてしまいます。
 それから、コンストラクタの構文について少し触れておくと、OCamlにおける{...}はレコードを作成するためのものでした。
# type r = {a : int};;
type r = { a : int; }

# {a = 10};;
- : r = {a = 10}
 F#ではどうかといいますと、結局は似たり寄ったりです。実際、上記の構文はF#でも同じように動作します。
 この構文がコンストラクタ内でも使われているわけですが、F#のコンストラクタはいわば「何らかの引数を取って自分自身の型のインスタンスを返す」メソッドのようなものと位置づけられているようです。つまり、返り値の型は最初から判明しています。そこで{...}の構文を返り値にしようとすれば、当然ながら自身のインスタンスを作成することを試みるでしょう。先の{x = 0}の場合であれば、メンバ変数xに0が設定された自分自身のインスタンスを返します。何とも分かりづらいですが、Perlのblessよりはマシでしょうか。
 なお、.NETにはプロパティが存在しますが、F#にもプロパティ構文が用意されています。こちらもMono 1.2.6の時期から構文が変わっていないので、迷うまでもなく作成できました。上記のxをプロパティとする場合には、以下のようになります。
type Some = class
  val mutable x : int
  new () = {x = 0}
  member this.X
    with get () = this.x
    and set v = this.x <- v
  member this.PlusX (v : int) : unit = this.X <- this.X + v
end;;

let s = new Some () in
  s.PlusX 9; s.PlusX 8; Printf.printf "Total: %d" s.X
 プロパティが使える以上、「代入もしくは取得のみを許可するプロパティ」も作れるはずですが、1.2.6の時期には試していませんでした。そこで、読み取り専用プロパティを作成してみようと、ひとまずsetを削除してみたところ、上手くいってしまいました。
type Some = class
  val mutable x : int
  new () = {x = 0}
  member this.X
    with get () = this.x
  member this.PlusX (v : int) : unit = this.x <- this.X + v
end;;

let s = new Some () in
  s.PlusX 9; s.PlusX 8; Printf.printf "Total: %d" s.X
 ただのクラスだけでなく、ジェネリッククラスを作る方法も考えてみます。それにしても、「ジェネリック機構」と聞くと私はどうしても関数型言語を連想してしまいます。Adaなどの先見の明の言語は残念ながら一般への普及には至らず、C++でようやくテンプレートが生まれ、JavaもC#も最初はこの機構を採用せず、C#の2.0でようやくサポートを開始し、Javaもそれに追随(しかもJavaのは単なる糖衣構文の一種で、コンパイル結果にジェネリックの型データは含まれない)、やっと日の目を見るに至ったという印象です。
 一方、十分な型チェックがある関数型においては、ほぼ必ずと言っても過言ではないほどジェネリック機構(呼び名は違いますが)が用意されています。そもそも関数型の教科書でごくごく最初に出てくるmapですら、('a -> 'b) -> 'a list -> 'b listなのですから。
 OCamlでジェネリッククラス(とC#では呼ばれるもの)が作成できるのは言うまでもありません。
class ['t] holder(first_data : 't) = object
	val mutable data : 't = first_data
	method next (d : 't) : 't =
		let old = data in data <- d; old
end;;

let h : int holder = new holder 5 in
	Printf.printf "%d\n" (h#next 10);
	Printf.printf "%d" (h#next 15)
 コンストラクタで初期値を指定し、nextメソッドを使用すると古い値を取得して新しい値をセットする、単純なクラスです。当然、何型に対しても使用できます。
 C#などではClassName<T>と書きますが、OCamlでは['t] classnameです。型を指定する際にも、「int holder」のように型が先に来ます。「int list」などもこの類型です。私は未だに順番を間違えてしまったりします
 .NET系列のF#でも、書き方はおおむね同じです。
type 'T Holder = class
  val mutable data : 'T
  new (d : 'T) = {data = d}
  member this.Next (d : 'T) : 'T =
    let old = this.data in
      this.data <- d; old
end;;

let h : int Holder = Holder 5 in
  Printf.printf "%d\n" (h.Next 10);
  Printf.printf "%d" (h.Next 15)
 これで正しいのかは自信ありませんが、ひとまず動作はしますので、間違いではなさそうです。
 しかしながら、newがつかない点が気になったため、(あてずっぽうで)以下のように書き直してみたところ、今度はnewつきで同様の結果が得られました。本当に同様の処理が行われているかは不明ですが、結果は同じです。
type 'T Holder = class
  val mutable data : 'T
  new (d : 'T) = {data = d}
  member this.Next (d : 'T) : 'T =
    let old = this.data in
      this.data <- d; old
end;;

let h : int Holder = new Holder<int> 5 in
  Printf.printf "%d\n" (h.Next 10);
  Printf.printf "%d" (h.Next 15)
 F#のクラス関係の構文はある程度C#などの言語に近いものの、C#の経験者がF#をも即座に使えるほどではありませんし、かといってOCaml使いも勉強なくしてはF#のクラスを使用できないという、ある種の中途半端さも抱えている印象です。.NETに関数型言語を導入するからには、仕方のない点でしょうか。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]
<- 前の記事を参照 次の記事を参照 ->

- Blog by yamicha.com -