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
ブログ - yamicha.com's Blog

 存在する記事 776 件の中から 41-45 件を表示しています。
新型インフルエンザの恐怖
2009/11/01(Sun)21:19:49
 このところ、新型インフルエンザの被害拡大がよりいっそう社会問題化しているようです。マスコミも連日のようにこれを報じ、新聞では社説のテーマに取り上げなかった社の方が珍しいほどです。もともとインフルエンザは冬に流行する傾向があるため、本格的な冬にかけてさらに大流行を起こす懸念は否定できず、医療体制の問題が問われている他、ワクチンをどう配分するかも問題となっています。
 何事も「備えあれば憂いなし」ですので、新型インフルエンザに対する正しい知識を身につけ、備えを怠らないのは良いことです。マスコミも、新型インフルエンザに関する正確な情報を提供して国民の知識を充実させ、啓蒙活動を行うのであれば、その報道には価値があるといえます。多くの国民が正しい知識を習得し、いたずらにあわてずに対策をすることができれば、被害を最小限に抑えられるに違いありません。
 しかしながら、果たして国民の多くはそれを実行できているでしょうか。マスコミはそのような報道を行っているでしょうか。おそらくそれを行っている人も少なくないはずですが、残念ながら虚像を作り上げるような報道と、虚像に踊らされる人間が非常に多いように見受けられます。もともと西洋文化であるクリスマスやハロウィーンまでお祭りにしてしまうなど、日本人はとかくお祭りが好きな民族のようですが、新型インフルエンザさえもそのレベルで扱われているような気がしてなりません。
 無論、正しい知識を身につけ、正確な備えを行うのであれば、何の問題もありません。しかし、あまりにも派手に騒ぎすぎたり、時には不確かなデマまで飛び交う状況となれば、それは百害あって一利なしと言わざるを得ません。かつて関東大震災が発生した際、地震とそれに付随する火災によって多くの悲劇が生じましたが、さらに「朝鮮人が井戸に毒を入れている」というデマまでもが飛び交い、朝鮮人やそう誤認された日本人に死傷者が出るなど、さらなる悲劇を生み出しました。最近のインフルエンザ騒ぎに感じるのは、まさにこのような印象です。
 当然のことながら、余程の無政府状態にもならない限り、現代日本でここまでの騒乱は発生し得ないでしょう。ところが、さすがに殺傷事件までには達しないにしても、その土壌は確かに存在しています。日本で新型インフルエンザが確認された際、修学旅行でインフルエンザを持ち込んだとされる生徒が所属していた学校に対して電話で文句をつけ、謝罪を要求した者がいたというのです。また、インターネット上などで感染生徒に対する不当な誹謗中傷が行われたことも問題となっています。ちなみに、新型インフルエンザ自体はその前からすでに一部で流行しており、ここで初めて正式に新型インフルエンザであることがが確認されただけという説もあるようです。
 このような状況に際し、マスコミには正しい情報と冷静な対応を呼びかける責務があるはずです。ところが、そのマスコミもまた火に油を注いでいるばかりか、自ら火種を作っている有様です。関東大震災の際、ただのデマ程度の噂が暴動や殺傷にまで発展した原因は、おそらく疑心暗鬼にあるはずですが、新型インフルエンザ問題でのマスコミの対応は、まさにそれをあおっているようにしか見えません。
 マスコミの影響力の大きさは、今さら言うまでもありません。健康番組が「納豆を食べるとダイエットができる」と称すれば、納豆があっという間に売り切れてしまい、逆に捏造が発覚した後はさっぱり売れなくなってしまい、本当に良いものを作ろうとしている納豆業者が最大の被害者となりました。鳥インフルエンザが報道された際には鳥がさっぱり売れなくなる風評被害を生じ、それ以外にも実に様々な被害をもたらしています。あるいは、健康や病気にかかわらない分野であっても、昨今は昔に比べて殺人が増えている、少年犯罪が増えているなどという、統計資料を見れば一目で分かるデマを流布し、無用な不安をあおっています。国民がそのようなものを信用しないのであれば何の問題もありませんが、実際には納豆が店頭から消えてしまいました。
 どういうわけか、新型インフルエンザでは死者が発生するたびに報道がなされていると言っても過言ではなく、これによって「致死性」の印象から恐怖を抱く人も少なくないはずですが、実際には既存のインフルエンザでも毎年多数の人が亡くなっています。致死率は0.5%程度で季節性より高いともされますが、医者にかからぬまま、あるいは不健在感染や風邪と思い込むなどして自分でも気づかぬまま治癒してしまう人も非常に多いと考えられ、それを合計すると0.05%程度ではないかとする意見もあります。少なくとも、既存のインフルエンザを大きく上回るものではないと考えるのが妥当でしょう。むしろ、もし本ウイルスが感染性・致死性ともに極めて高く、毎日数百数千の人が犠牲になるような悪魔のウイルスであるのなら、犠牲者が出るたびにいちいち報道することはできないわけですから、個々の犠牲者に対する大きな報道は致死性の低さの証左と捉えるべきでしょう。
 無論、今は弱毒性のインフルエンザであっても、後に強力な毒性を持ってしまう可能性はありますし、いくら弱毒性でも感染拡大に対する警戒を怠ってはいけませんが、注意を促す報道と疑心暗鬼を誘う報道は全くの別物です。それどころか、あまりに新型インフルエンザの危機が誇張されて報道されるせいで、やはり強力な感染力と致死率を持つ季節性インフルエンザや、警戒を怠ってはならない鳥インフルエンザへの注意がお留守になっています。
 また、過剰反応から病院に人が殺到する現象は現時点でも発生しており、それによって医療機関がパンクして必要な治療が行えなくなったり、二次感染が発生してしまう懸念が生じています。それ以外にも過剰反応は様々な余波をもたらしており、実害が生じています。納豆騒動は納豆が正しく理解されている、あるいは納豆を食べてダイエットなる簡単な話はあり得ないと理解されていれば、最初から発生しなかったはずですし、鳥インフルエンザ問題にしても、食用肉からの感染の可能性がないことが理解されていれば、鶏肉が売れなくなることはなかったはずです。これらと同様に、新型インフルエンザについて本当に正しい理解がなされていれば、無用な過剰反応は抑制できるはずなのです。
 ワクチン配備と投与も結構ですが、ワクチンが万能でない点には留意しなくてはなりません。国民は案外冷静なのか、「ワクチン接種を受けたくない」と考える人は少なからず存在するようですが、事実としてワクチンは絶対的なものではありません。既存のワクチンも様々な副作用が報告されており、あまり効果を発揮しない場合もあることから、老人などの高リスク者は接種を推奨されてはいるものの、あまり接種を行うべきでないとの意見もあります。ましてや、新型に対するワクチンは突貫製造の上に十分な知見が得られていません。一応のテストは行われているにしても、テストを行った末に認可されたはずの薬に大問題が生じる場合があるのを見るまでもなく、実際の効用や副作用は使ってみなくては分かりません。このワクチンが有意に感染率を低下させるのが確かであれば、高リスク者への接種を行うのは妥当な策ではありますが、少なくとも万能であると考えてはいけません。
 今回の新型インフルエンザは、せいぜい季節性に匹敵する程度の致死性しかない軽微なものでしたので、マスコミの過剰報道にせよ、国民の過剰反応にせよ、害悪ではあっても致命的なほどの混乱は生じていませんが、私が危惧するのはその先です。もし免疫が暴発する強毒性鳥インフルエンザが大発生したり、エボラ出血熱や天然痘のような極めて感染力と致死率の高い(致死率は前者で5〜9割、後者で3〜5割程度とされる。「天然痘」そのものは世界から根絶されたが、類似ウイルスが人間への感染性を獲得する可能性を指摘する声もある)病気が流行した場合、マスコミはどのようにこれを報道し、国民はいかなる反応を示すのでしょうか。たかだか今回の新型インフルエンザでさえ、学校に中傷の電話をかける連中がいたり、これだけパニックを起こしたりする有様なのです。それこそ、医療機関の麻痺や関東大震災の再来、その他様々な大問題が現実のものとなる可能性が否定できません。

 まずは以前のおさらいより。OCamlなどの諸言語が丸カッコ(...)を使ってタプルを作成するのと異なり、Erlangのタプル型は{...}を使って作成することになっています。少々紛らわしいですが、おそらく慣れの問題でしょう。そのような人がどれほど存在するのかは不明ですが、Erlangを最初に習得した人であれば、丸カッコを使用する方が紛らわしく見えるかもしれません。
 余談ながら、OCamlでは「()」(空のタプル)がunitなる特殊なもの(主にvoidとしての役割)を表していますし、F#ではタプルがCなどの関数呼び出しのように見えるのを利用してか、「Console.WriteLine()」のように表記すると引数なしのメソッドが呼ばれ、「Some(a , b)」ならaとbを引数とするメソッドが呼ばれる仕組みとなっています。すなわち、C#などの「int Some(int , int)」は、F#では「int * int -> int」に当たります(*1)。これらのような分かりづらい性質を考えると、タプルを丸カッコで扱わないErlangの方が合理的な気がしなくもありません。

(*1)09/11/04 「(int * int) -> int」と書いていたところを、いげ太さんよりご指摘をいただき、修正しました。本来カッコなど全く必要ないところを、タプル作成の表記に気を取られて誤っていました(F#でもOCamlでもカッコなど全く必要ない場面であるはずなのに、この何の脈略もないミスは自分でも不思議です)。ご指導ありがとうございます。

 それでは、タプルから値を取り出す場合はどうするのでしょうか。そこは関数型言語ですから、パターンマッチに限ります。
-module(blog).
-export([calc/2]).

calc(V , {add , D}) -> V + D;
calc(V , {subtract , D}) -> V - D.
 タプルの1つ目のアトムがaddであれば足し算、subtractであれば引き算を行う簡単なサンプルです。
1> blog:calc(100 , {add , 10}).
110

2> blog:calc(100 , {subtract , 64}).
36
 これを使ってバリアントの真似事でも行ってみます。さすがにPrologを基にしているだけはあって、とにかく条件にマッチさえすれば何の問題もなく動作します。
-module(blog).
-export([value/1]).

value({real , V}) -> io:fwrite("Real: ~f~n" , [V]);
value({complex , V1 , V2}) -> io:fwrite("Complex: ~f , ~f~n" , [V1 , V2]);
value({nan}) -> io:fwrite("Not A Number~n").
% Erlang では何型であってもとにかくマッチさえすれば動作するので
% nan は別にタプルにしなくても(直接アトムを使っても)構わない
 実数、複素数、NaNのいずれかを取る関数(という設定)です。サンプルであるため、ここでは単に中身を表示するだけですが、実際に計算を行わせても面白いでしょう。OCamlで言うところの以下のようなバリアントを仮想しています。
type num = Real of float | Complex of (float * float) | NaN;;
 後は単に適当なタプルを渡すだけです。
1> blog:value({real , 2.71828}).
Real: 2.718280
ok

2> blog:value({complex , 10.0 , 5.0}).
Complex: 10.000000 , 5.000000
ok

3> blog:value({nan}).                 
Not A Number
ok
 これを踏まえて、レコードについて。
 他の多くの言語と同様、Erlangもレコードをサポートしています。独立した機能というよりは、ほとんど「名前付きタプル」です。
 まず以下のような記述を行い、レコードを宣言するようです。
% 単純な書き方
-record(book , {title , author}).

% デフォルト値も設定できる
-record(book , {title = "" , author}).
 デフォルト値を明示的に指定しなかった場合、デフォルト値は「undefined」(アトム)とみなされます。ブール値といい、Erlangのアトムはなかなか巧妙に使われています。
 レコードの「オブジェクト」(なる言葉をErlangで使うのが適切かは不明ですが)を作成する際には、シャープ記号に続いてレコード名を書き、その後ろに値を並べます。
% ごく普通の作り方
create_book(Title , Author) -> #book{title = Title , author = Author}.

% 通常のタプルと違い、値は任意の順番で書ける
create_book(Title , Author) -> #book{author = Author , title = Title}.

% 値指定の一部または全部を省略してもよい
% 省略した場合、デフォルト値があるならその値、ないなら undefined が格納される
create_book(Title , Author) -> #book{title = Title}.

% このような書き方はできない模様
% create_book(Title , Author) -> #book{Title , Author}.
 レコードの中身を取得する際には、「object#recordname.varname」の形式を取ります。
get_title(Book) -> Book#book.title.
% 末尾のピリオドは取得の構文の一部ではありません。念のため
 これが型のはっきりした言語であれば、例えばCなら
struct Book book;
...
book.title;
 これで(book変数はBook型であると分かっているため)書名を取得できますし、OCamlなどの関数型言語でも同様です。しかしながら、Erlangでは型の自由度が高く、いかなる型が渡されるか分からないため、このような記法となっているのでしょう。
 さらに言えば、実はそもそもレコード自体が「特定の手順に従ってタプルを取り扱う」一種のマクロか糖衣構文に近い扱いのようで、レコードのオブジェクトの実態はレコード名をアトムとして含むタプルです。
 ここに以下のようなプログラムがあるとして、
-module(blog).
-export([create_book/2 , get_title/1]).
-record(book , {title , author}).

create_book(Title , Author) -> #book{title = Title , author = Author}.
get_title(Book) -> Book#book.title.
 このcreate_bookを呼び出して、bookレコードのデータを作成してみると、
1> blog:create_book("Design Pattern" , "four gangs").
{book,"Design Pattern","four gangs"}
 {レコード名 , 値...}のタプルが返ってきました。それなら、最初からこの形式でタプルを作り、当該レコードを引数に取る関数に渡した場合、一体どうなるのでしょうか。
1> blog:get_title({book , "Introduction Erlang" , "Ericsson"}).
"Introduction Erlang"
 この通り、何事もなく動作してしまいます。すなわち、レコードの正体は以上のようなものであると分かります。
 また、レコードを使用すれば値の修正も容易にできそうです。以下の例であれば、set_title関数は「書名を変更するものである」ことが一目瞭然です。
-module(blog).
-export([create_book/2 , get_title/1 , set_title/2]).
-record(book , {title , author}).

create_book(Title , Author) -> #book{title = Title , author = Author}.
get_title(Book) -> Book#book.title.

% 既存のデータのタイトルのみを変更する関数
% 無論、元の値を変更(参照透過性を破壊)するのではなく、
% 新しい値を格納した新しいオブジェクトを生成して返す
set_title(Book , Title) -> Book#book{title = Title}.
 これは以下のように使用できます。
1> B = blog:create_book("(TBD)" , "Jane Doe").                   
{book,"(TBD)","Jane Doe"}

2> blog:set_title(B , "Erlang Process Trainer").
{book,"Erlang Process Trainer","Jane Doe"}
 つくづく奇妙ながらも面白い言語です。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 1]

日本憂政
2009/10/25(Sun)13:42:17
 政権交代の影響により、日本郵政の西川氏が事実上罷免されましたが、今度はその後任人事が問題となっているようです。新社長とされるのは斉藤次郎氏ですが、氏は1995年まで大蔵省の事務次官を務めており、民主党が進める「脱官僚・天下り」との整合性が取れていないとして批判されています。また、日銀の新総裁を決定する際には、民主党は財務官僚出身であることを理由として武藤氏や田波氏を総裁とする人事に強硬に反対し、結果として副総裁になるはずの白川氏が総裁となりましたが、その一方で今回の元官僚の起用とあって、自民党新総裁の谷垣氏らは批判を強めています。
 斉藤氏が官僚を辞めてから14年が経過しており、この期間をどの程度重く考慮するかによっても評価は違ってくるはずですが、少なくともこの人事が脱官僚・天下り路線を推進するものであるとは言いがたく、その点で批判を受けるのは当然でしょう。下手をすると「脱官僚」の目標自体も頓挫しかねないほどの問題ですので、民主党が説明責任を果たさなくてはならないのは言うまでもありません。しかしながら、日銀を引き合いに出して今回の人事を批判する主張には同意しかねます。日銀の場合とはあまりに状況が違いすぎるためです。
 経済関係の問題は難解であるため、何となく「民主党が武藤・田波総裁案に反対したのは官僚出身だから」と捉えている人が多いとしても無理のないことですが、実際には単に元官僚なのが理由と捉えるのは正しくありません。日本銀行法では、日銀は政府と連絡を密にし、十分な意思疎通を図らなくてはならない旨が定められていますが、一方では独立性も必要であり、「金融と財政の分離」の観点からも問題が生じてくる恐れがあります。
 総裁と財務省とのパイプが十分残っていれば、日銀の独立性が損なわれる可能性は否定できません。以前に日銀が金融緩和政策を緩めようとした際、政府が立法権をちらつかせて日銀をけん制したことがありましたが、これなどは独立性の重要さを示す事例でしょう。政府としては、自政権の評価がかかっていたり、近日中の選挙が予想されるタイミングでは、景気の腰を折る可能性がある策を実行されては困るなど、様々な力学が絡んできます。すなわち、日銀の独立性を担保するために、元財務官僚の人間を総裁にしない行為には、ある程度の妥当性があります。
 無論、日銀同様に日本郵政にも独立性が必要であるから、元官僚を社長にすべきでないとの意見はあってもおかしくありませんし、これもまた重要なことです。しかしながら、西川氏が不公正な可能性の否定できない行為を行って問題視され、鳩山邦夫氏など自民党内の人間からも異論が出るほどであったのは周知の事実ですし、麻生氏は氏を排除しようとしたものの、小泉・竹中院政に先手を打たれて外堀を固められてしまい、逆に鳩山氏を切らざるを得なくなるなど、こちらも政治力学が非常に強く作用しています。したがって、独立性の観点を問題にするのであれば、西川氏の時点からの総括が必要でしょう。
 また、人事の透明性の面から見ても、確かに斉藤氏の起用は「脱天下り」に反するといえなくもありませんが、日銀の場合は「たすきがけ人事」という不透明な慣習が具体的に存在しており、財務官僚の起用はそれの再燃や疑念を招きかねない状況でした。具体的に存在する不透明な人事の懸念を問題視したものと考えれば、日銀の武藤氏ら起用に対する民主党の反対は、直ちに「元官僚の起用」を全否定したものであるとは言いがたく、今回の人事と日銀とではそれなりの違いがあると言わざるを得ません。
 このように、条件が違いすぎる日銀を引き合いに出して今回の人事を否定したとしても、どこかで話がかみ合わない事態に陥り、不毛な議論ともなりかねません。もし谷垣氏らがそのような批判に終始するのであれば、「自民党の野党ぶりも板についてきた」と皮肉のひとつも言いたくなるところです。
 谷垣氏がやるべきは、日銀総裁うんぬんではなく日本郵政の社長に斉藤氏が就任することに対する懸念や問題点を指摘し、ひいては連立与党の郵政の方針をただすことです。日本郵政社長としての斉藤氏の手腕は未知数ですが、亀井氏がかかわっている点からして民営化に消極的なのはほぼ間違いなく、政権時には郵政民営化を進めてきた自民党としては、日銀を引き合いに出して粗を探すより、郵政政策に関して論じるべき場面です。民主党の側も、国民新党との関係もあり、なかなか明確なスタンスが打ち出しにくいとみられますので、攻勢をかける上でも効果的でしょう。自民党や谷垣氏としても、仮に民主党が批判を容れて斉藤人事を撤回し、郵政民営化に反対で民間出身の別の人を社長につけたとしても、おそらく批判は行うはずで、「日銀」の問題が本質的なものでないことが分かります。
 確かに、政治や経済といった関係の話は難しい場合が多く、委細に渡って郵政の問題をただすより「斉藤氏の起用は天下りの官僚人事で、日銀総裁人事の対応と矛盾している」と主張した方が、何となく民主党に悪印象を抱かせることはできそうですが、それでは困ります。目立つばかりの小泉氏や麻生氏と違い、どちらかといえば政策通タイプの谷垣氏だけに、郵政についての議論が行われる希望がないとはいえません。

 ところで、次の参院選で民主党単独政権が誕生した場合はともかく、今のところは郵政民営化に消極的な立場を取っている連立与党ですが、その姿勢に対して「民営化は郵政選挙であれだけの民意を得たのだから、安易に止めるのは許されない」との意見が存在するようです。それについて少々触れておきます。
 私としては、そうした言い分自体は決して理解できないわけではありませんが、これに明確に反対します。なぜなら、郵政選挙において少なからぬ国民は、郵政民営化のデメリットをほとんど認識していなかったためです。
 はっきり言って、郵政選挙の際には調べもせずに小泉氏に賛同していながら、後になって郵便局が不便になったことに文句を言うような人間に、私は大変深く失望しています。常識的に考えて、「郵政民営化を実現すれば日本はバラ色で、その上副作用もない」などという上手い話があるわけがないのです。したがって、小泉氏不支持であったのに不便を負わされている人は気の毒と言うよりありませんが、小泉氏の郵政を支持した上で不便さに文句をつけるなど、選挙の結果責任を侮っているとしか言いようがなく、本来なら考慮する必要すらありません。
 しかしながら、小泉氏はあたかも郵政民営化が正義であるような主張を行い、デメリットどころか郵政民営化なるものが何なのかも知らぬまま支持していた人も存在するようです。スリードの低IQ戦略によるものですが、これでは後々不満が出るのも当然で、小泉氏のやり方には大いに問題があったといえるでしょう。
 結果、不便になるなどとは聞いていなかった人々が当然のごとく憤り、実際に直接被害をこうむった人、あるいは不安を覚えた人が自民党を見限り、それが民主党大勝の原因の1つとなったことは十分に考えられます。また、党内にも異論が出てくる状況が予想され、事実として麻生氏は郵政民営化を否定するかのような発言を行うなど、明らかにゆり戻しの機運が発生していました。ひとたびそうなってしまっては、いずれ郵政見直しの動きが出てくるのも必然の流れです。
 政権交代により、極端な場合は郵政民営化自体が頓挫しかねず、控えめに見ても減速するのは間違いありません。あの低IQ選挙と郵政の問題が自民敗北の遠因となったのであれば、郵政民営化が何なのかも分からぬまま支持していた連中はともかく、郵政民営化のデメリットは理解しつつも、それでも民営化は必要だから断行しなくてはならないと考え、小泉氏と郵政民営化を支持していた支持者すら裏切る結果となりました。これがあの華々しい低IQ選挙の結末です。まさに「選挙に勝って、勝負に負けた」ようなものです。勝負である郵政民営化は道半ばで阻まれてしまうのに、選挙に勝ったせいで金配りその他はことごとく通され、無賃残業合法化は通される寸前まで行くなど、何とも代償の大きい選挙でした。
 再び自民党が政権を取り、政権を競って切磋琢磨するのは大いに結構ですが、あのような選挙はもう二度とないことを望みます。

 Prologでは、例えば「アーランは人間である」「人間は生物である」といった「事実」を書くことができます。
human(ada).
human(haskell).
human(erlang).
cat(tom).
dolphine(sakila).

creature(X) :- human(X).
creature(X) :- cat(X).
creature(X) :- dolphine(X).
 これを読み込んだ後、例えば以下のような問い合わせが可能です。
% エイダは人間であるか
?- human(ada).
true.

% 誰が人間であるか
?- human(X).
X = ada ;
X = haskell ;
X = erlang.

% サキラは生物であるか
?- creature(sakila).
true.
 これが論理型言語たるPrologの特徴なのですが、果たしてPrologの派生であるErlangにこの種の機能はあるのでしょうか。
 Erlangでの類似機能は「Atom」と呼ばれており、命名規則もPrologに従っています。すなわち、先頭を小文字で記述した単語はAtomとみなされます。また、Erlangのリファレンスマニュアルによれば、文字列をシングルクォートで囲んだ場合、先頭の文字にかかわらずAtomとみなされるようです。
 したがって、以下のものはすべてAtomとなります。
atom
atom_type
atomType
'atom'
'atom type'
'Atom'
 シングルクォートで囲んでいないAtomと囲んだAtomは、両方同じものとみなされます。
1> atom == 'atom'.
true

2> atomType == 'atomType'.
true
 このAtom、平たく言えば定数のようなものなのですが、おそらくPrologから着想を得たものとみられるだけはあり、かなり色々な使い方ができそうです。他の言語でいえば、Lispのシンボルにも類似しています。
 手続き型で使用される定数の類のように、単にifなどで比較するだけでも使用できます。以下のプログラムは、1つ目の引数Xが数値、2つ目の引数SがAtomを取り、Atomの値がinclementの場合は数値に1を加算して返し、declementの場合は1を減算して返し、いずれでもない場合はそのまま返す、簡単なサンプルです。
-module(blog).
-export([num_action/2]).

num_action(X , S) -> if
	S == inclement -> X + 1;
	S == declement -> X - 1;
	true -> X
	end.
 これは以下のように呼び出せます。
1> blog:num_action(10 , inclement).
11

2> blog:num_action(5 , declement). 
4

% inclement または declement 以外のあらゆる Atom を渡した場合
3> blog:num_action(5 , any_other_atom).
5
 ただ、ErlangのAtomで面白い点は、何と言ってもパターンマッチでしょう。Prologを基にした関数型言語だけに、似たような書き方が可能となっています。
 以下のプログラムは、先ほどのPrologコードのhumanと類似しています。さすがにPrologと違って「誰が人間であるかを列挙」したりはできませんが、「アーランは人間か」を問い合わせることなら可能です。
-module(blog).
-export([human/1]).

human(ada) -> true;
human(haskell) -> true;
human(erlang) -> true.
 ただし、上記ではada、haskell、erlangのいずれかのAtomが引数として渡された場合の動作しか定義されておらず、それ以外のAtomが渡された場合の動作が存在しませんので、これら以外のAtomを渡すと例外が発生します。例外ではなくfalseを返すには、単に以下のようにするだけです。
-module(blog).
-export([human/1]).

human(ada) -> true;
human(haskell) -> true;
human(erlang) -> true;
human(_) -> false.
 もう少しPrologの真似事を行ってみます。Erlangは関数型言語ですので、論理型言語としての側面(「定義された人間をすべて列挙」するような逆引きの機能、複数経路の探索など)は持っていませんが、「サキラは生物であるか」を調べる関数程度なら簡単に作成できます。
-module(blog).
-export([human/1 , cat/1 , dolphine/1 , creature/1]).

human(ada) -> true;
human(haskell) -> true;
human(erlang) -> true;
human(_) -> false.

cat(tom) -> true;
cat(_) -> false.

dolphine(sakila) -> true;
dolphine(_) -> false.

creature(X) -> human(X) orelse cat(X) orelse dolphine(X).
 実際に問い合わせてみると、
1> blog:creature(sakila).
true

2> blog:creature(erlang).
true

3> blog:creature(plant).  
false
 サキラもアーランも生物であるとみなされているようです。植物(というより定義されていないあらゆるもの)は生物とはみなされません。
 ちなみに、Erlangではtrueもfalseもその実体はAtomです。
There is no Boolean data type in Erlang. Instead the atoms true and false are used to denote Boolean values.
 当然、以下のような式も成り立ちます。
1> true == 'true'.
true

2> false == 'false'.
true
 また、atom_to_list及びlist_to_atom関数を使用すると、Atomを文字列にしたり文字列をAtomにしたりできるようです(「Strings are enclosed in double quotes ("), but is not a data type in Erlang.」とのことで、「文字列」の呼称自体正しくないかもしれませんが)。文字列の比較と比べてパフォーマンス上の利点があるのであれば、辞書型のキーなどの使い道もありそうです。
% 追加と取得の操作しかなく、何の最適化もない非常に単純な辞書型の実装
% Erlang のタプルは丸カッコではなく {...} でくくる
-module(blog).
-export([add/3 , get/2]).

add(X , K , V) -> [{K , V} | X].
get([{K , V} | _] , K) -> V;
get([_ | XS] , K) -> get(XS , K);
get([] , _) -> throw("Not found.").

% 実際に使用
1> D_1 = blog:add([] , ada , "Ada Lovelace").    
[{ada,"Ada Lovelace"}]

2> D_2 = blog:add(D_1 , haskell , "Haskell Curry").
[{haskell,"Haskell Curry"},{ada,"Ada Lovelace"}]

3> D_3 = blog:add(D_2 , erlang , "Agner Erlang").         
[{erlang,"Agner Erlang"},
 {haskell,"Haskell Curry"},
 {ada,"Ada Lovelace"}]

4> blog:get(D_3 , haskell).
"Haskell Curry"

5> blog:get(D_3 , erlang). 
"Agner Erlang"

6> blog:get(D_3 , unknown).
** exception throw: "Not found."
     in function  blog:get/2
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

用済団体連合会
2009/10/18(Sun)19:58:38
 政権が変わったことで、国会や国政に直接関係のない部分でも様々な変化が起こりつつありますが、象徴的なのが経団連の弱体化です。選挙前に政権交代の兆しが見え始めた段階から、経団連の行動はかなり慎重なものへと変貌しつつあり、政権交代後はさらにその傾向が強くなりました。これまで献金の目安として示してきた政策の格付けも、今年は見送りに追い込まれています。
 何はともあれ、経団連が以前より政治から遠ざけられるのは非常に良いことです。勘違いしてはいけない点なのですが、経団連はあくまで「大企業の、大企業による、大企業のための政策を実現させるための組織」に過ぎず、決して正義の味方や憂国の士ではありません。経団連と蜜月の関係にあった自民党と違い、民主党が彼らと距離を置こうとしているのは、民主党の政策理念からしても、おおむね正しい方向性です。
 経団連の代表的な主張として、「消費税を上げて法人税を下げる」などといったものがありますが、私はこれを全くの逆効果と考えているものの、「企業主導の景気回復」を期待したものとも取れますので、これだけで経団連が自分のことしか考えていないと評するのは早計です。しかしながら、談合発覚時に取り立てる金額を欧米並みに引き上げる案が出た際には、経団連が頑強に抵抗し、引き上げ幅を縮小されてしまいました。また、公益通報者保護法も経団連によって骨抜きにされています。三菱や雪印偽装、ミートホープ問題などが公益通報で発覚したことを考えれば、国民の生命すら脅かしかねない行為と断じざるを得ません。無賃残業合法化が検討された際には、当時の政府が「年収900万円」を条件として、一般の人には適用しないとのアピールに腐心する一方、経団連は「年収400万円」をハードルにすることを主張しており、狙いは見えたも同然でした。ここまで徹底していると、さすがに弁護のしようもありません。
 今年は見送りとなった政策評価にしても、その実は2008年分を見れば一目瞭然です。A〜Eの5段階評価で、10項目について「合致度」「取組み」「実績」の3種類の評価がなされているのですが、以下の表は各党・各評価ごとにA〜Eの個数をまとめたものです。

評価 自由民主党 民主党
合致度 取組み 実績 合致度 取組み 実績
A 7 3 0 0 0 -
B 2 6 7 3 2 -
C 1 1 3 6 3 -
D 0 0 0 1 5 -
E 0 0 0 0 0 -

 産経新聞の「教科書の通信簿」も真っ青の恣意的評価です。民主党にAはなく、自民党にDはありません。公開は2008/9/17とされていますが、この時期にはすでに自民党は指導力を非常に失っており、同24日には福田氏が辞任してしまいます。この評価を献金の目安にしていたといいますが、どこからどう見ても「自民党に献金しなさい」という布告です。これでは当然、民主党政権下では自粛せざるを得ないでしょう。
 とはいえ、これは驚くべき評価ではありません。経団連は企業の利益のための団体であって、日本を住みよい社会にしようと考えているわけではありませんので、自己利益のために自分の意に沿う政党に献金し、懐柔しようとするのは当然です。先の格付け評価を見ても、評価を「合致度」と銘打ってある辺り、まだ正直であるともいえます。
 ともかく、この意を受けた自民党が派遣を解禁したり、法人税を下げようとしたり、無賃残業合法化を成立直前の段階まで持って行ったりと、様々な政策を行ってきたのは間違いありません。ただ、経団連の思惑と国を安定させる方策が一致しているうちは上手くいくのですが、昨今のように新自由主義経済が破綻寸前となり、世界的に疑問符がついてくると、あくまで自己利益を優先する経団連の主張にはことさら矛盾が目立ってきます。法人税減税の決まり文句「企業が海外に逃げる」はそれを端的に表していて、これはすなわち「時勢を誤った企業優先主義で日本がボロボロになり、利用価値がなくなったとしても、大企業は日本を見捨てて海外に逃げることができる」とも言い換えられます。
 今後の日本で二大政党制が定着するかはまだ分かりませんが、もし日本が定着の傾向に動いていれば、経団連の影響力が低下することはあっても、強化されることはあり得ません。しかも経団連はおそらく多くの国民に見放されており、悪印象を持たれています。かく言う私も、経団連が何らかの「国民・社会・日本に有利な」政策を提言した際には、必ず裏を疑うようになってしまいました。しかも、事実として大抵は何らかの裏があります。
 二大政党制が定着すれば、献金で政権を動かして望みの政策を実現させるというモデルは、もはや時代遅れのものとなる可能性もあります。この「金も出すが口も出す」方針もまた国民に支持されているとは言いがたく、民主党は禁止の方針さえ打ち出しています。さらに、政権交代がいつでも可能となれば、経団連が自分勝手な政策を提言したとしても、各党はそれを実現するのが困難になります。このまま行けば、いずれ「我が物顔」が通用しなくなる日が来るでしょう。
 経団連は企業の団体のはずですが、もはや信用は失うところまで失っています。もはや自己利益だけを考え、政党にすり寄っていても相手にされなくなる時代となりつつありますが、果たして時勢を読み、信用を回復することはできるのでしょうか。
 ところで、亀井氏が経団連会長の御手洗氏に「家族間の殺人事件が増えたのは、大企業が日本型経営を捨てて人間を人間として扱わなくなったから」であると発言していたことが以前に取り上げられましたが、これについても少し取り上げておきましょう。
 残念ながら断定するほどの資料は見つけられませんでしたが、亀井氏の発言はおそらくデマです。家族間の殺人がどうかは不明ですが、少なくとも殺人事件全体に関しては、戦後から1990年付近までほとんどの時期において減少を続けており、特に1985年から90年にかけては大幅に減少し、その後はほぼ一定して低い水準が続いています。すなわち、現在の水準に落ち着いた1990年付近以前には、少なくとも今より多くの殺人が起きていたことになり、もし家族間殺人の割合が今と昔でさほど変わっていないのであれば、下手すると人口比で今の4倍も家族間の殺し合いが起きていた時代があったといえます。また、昔より今の方が家族間殺人の割合が多いとしても、「殺人の件数が減ったのは、もっぱら公共性の高い殺人が減ったため」とも考えられます。さらにさかのぼれば、親が子を殺したり売り払うことなど当たり前で、罪にすらならない時代もありました。
 ちなみに、日本にはかつて「尊属殺」という罪があり、無期懲役か死刑という大変重い刑罰となっていましたが、栃木実父殺し事件で違憲判決が出され(一応補足しておくなら、この時の違憲判決は「減刑しても執行猶予にもできないほどの罪は重すぎる」というもので、必ずしも罪自体を違憲とするものではありませんでしたが)、法律自体はいつもながら自民党の意味不明な家族観による抵抗で削除されなかったものの、実際には全く運用されなくなり、しばらく後にはついに正式に削除されました。
 ついでに、私の価値観を述べておくなら、家族間の殺人より公共性の高い殺人の方が重く見られるべきと考えています。つまり、この主張自体が事実の可能性は低いものの、亀井氏が「家族間の殺人が増えている」と憂慮しているのに対し、私はむしろ家族間ではない公共性の高い殺人、すなわち見ず知らずの人をいきなり襲ったり、通り魔で多数を殺傷したりといった事件の方が重大であり、憂慮すべきものと考えています。
 「歯に衣着せぬ」のは結構ですが、根拠もなくデマを唱えられては論全体の信頼性が落ちます。経団連の身勝手さと新自由主義の失敗は多くの人が指摘するところとみられますが、いい加減な発言はこの論全体の信頼性を貶め、「同類の背中を撃つ」結果となります。厳重に謹んでいただきたいものです。

 携帯電話会社の1つに「ソニー・エリクソン」なるものがあります。
 ソニーと関係のある会社であるのは一目瞭然ですが、それでは「エリクソン」とは何か。エリクソン社はスウェーデンの会社で、主に通信機器を手がける世界的な大企業です。そして、ソニー・エリクソンは同社とソニーの合弁会社です。
 このエリクソン社が設計して社内で使用し、後に一般にも公開されたプログラム言語が、Prolog類似の関数型言語「Erlang」(アーラン)です。名前の由来は数学者アグナー・アーランらしいのですが(その他、Ada、Haskell、Pascalなども数学者らの名前を取っている)、どうも「エリクソンの言語」を意識したネーミングでもあるようです。ちなみに「アーラン」は通信量の単位としても使われています。
 以前にひとまず並列処理まで扱ってみたことがありますが、私とProlog系統の文法は相性が悪いらしく(いくら覚えようとしても絶対に覚えられないVBに比べればかなりマシですが)、基本の書き方すら忘れてしまうため、いい加減に覚書をしたためておきます。
 ひとまず、関数型のサンプルとして非常に有名な「階乗」から。大変いい加減ですが、Prologなら以下のようになります。
fact(X , R) :- in_fact(X , 1 , R).
in_fact(X , R , R) :- X =< 1 , !.
in_fact(X , Y , R) :- V is X * Y , I is X - 1 , in_fact(I , V , R).
 これは以下のように呼び出します。
?- fact(0 , R).
R = 1.

?- fact(1 , R).
R = 1.

?- fact(5 , R).
R = 120.

?- fact(10 , R).
R = 3628800.
 これはこれで面白いのですが、使い方が特徴的でとっつきづらく、実用性の点でも問題があります。「Prologがもっと実用的な関数型言語であれば」という夢物語のひとつも語りたくなるところですが、この夢をErlangがかなえてくれました
 以上のプログラムをErlangで書き直すと、以下のようになります。ファイル名はblog.erlとしました。
-module(blog).
-export([fact/1]).

fact(X) -> in_fact(X , 1).
in_fact(0 , R) -> R;
in_fact(X , R) -> in_fact(X - 1 , X * R).
 -exportでは公開する関数名のリストを指定し、ここに書かれていない関数は外部からは呼び出せません。関数の指定方法といい、つくづくPrologそっくりです。Prolog同様、通常はピリオドが区切りとなりますが、上記サンプルでいうところのin_fact/2同士はセミコロンで区切っている点に注意が必要です。
 これをErlangコンソールから呼び出します。binディレクトリのerl.exeもしくはwerl.exeがそれですが、いずれもカレントディレクトリのファイルを探す仕様となっているため、ソースを保存したディレクトリをカレントにした状態でerlやwerlを実行する必要があります。werl.exeへのショートカットを作っておいて、プロパティの「作業フォルダ」を普段使用するディレクトリにしておけば、カレントディレクトリ設定後にwerl.exeを呼び出す作業が自動的に行われるため便利です。
1> c(blog).
{ok,blog}

2> blog:fact(0).
1

3> blog:fact(10).
3628800
 Prologには独特の使いづらさがありますので、Erlangの方が割と何も考えずに書けそうです。用途が違うため一概に比較はできませんが、論理型言語に起因する冗長さや複雑さとも無縁であるため、Prologに比べてかなり効率良く記述できます。また、Lispその他の多くの関数型言語と違い、関数名の後にカッコでくくって引数を指定する形式であるため、手続き型言語に慣れ親しんでいてもそれなりに読みやすいのも特徴です。
 参考までに、OCamlまたはF#では以下のようなコードとなります(あえて型の指定は省略しています)。私が初めて関数型言語を習得しようとした際、何がどのように関数なのかが分からず、非常に戸惑った記憶があります。その際に使用したのがHaskellでしたが、果てはカリー化まで出てきて大混乱しました。関数型未経験者にとってはErlangの方が取っ付きがよさそうです。
let fact x =
	let rec in_fact x r = match x with
	| 0 -> r;
	| _ -> in_fact (x - 1) (x * r) in
	in_fact x 1;;
 関数型言語といえばリスト処理ですが、これもまたPrologに非常に類似しています。まずPrologより。
sum(X , R) :- in_sum(X , 0 , R).
in_sum([X | XS] , S , R) :- NS is X + S , in_sum(XS , NS , R).
in_sum([] , R , R).
 リストの中身をすべて足し合わせるコードです。これをErlangで書くと、
-module(blog).
-export([sum/1]).

sum(X) -> in_sum(X , 0).
in_sum([X | XS] , S) -> in_sum(XS , X + S);
in_sum([] , S) -> S.
 論理型の冗長さを除けば、記述していることはほとんど同じです。
 一方、Erlangは関数型言語だけあって、お得意の高階関数は非常に簡単に書けます。Prologでも書けるには書けますが、若干煩雑です。例によってPrologより。
filter(F , X , R) :- in_filter(F , X , [] , R).
in_filter(F , [X | XS] , R , RR) :- call(F , [X]) , ! ,
	in_filter(F , XS , [X | R] , RR).
in_filter(F , [_ | XS] , R , RR) :- ! , in_filter(F , XS , R , RR).
in_filter(_ , [] , R , RR) :- rev(R , RR).

rev(X , R) :- in_rev(X , [] , R).
in_rev([X | XS] , S , R) :- in_rev(XS , [X | S] , R).
in_rev([] , R , R).

% 条件
over5(X) :- X > 5.
 呼び出した結果は以下の通りです。
?- filter(over5 , [1 , 9 , 2 , 8 , 3 , 7] , R).
R = [9, 8, 7].
 これと同等のコードをErlangで書くなら、
-module(blog).
-export([filter/2]).

filter(F , X) -> in_filter(F , X , []).
in_filter(F , [X | XS] , R) -> E = F(X) , in_filter(F , XS ,
	(if E -> [X | R]; true -> R end));
in_filter(_ , [] , R) -> rev(R).

rev(X) -> in_rev(X , []).
in_rev([X | XS] , R) -> in_rev(XS , [X | R]);
in_rev([] , R) -> R.
 といったところでしょうか。
 ifで直接F(X)を評価するのではなく、一旦Eに代入してから評価しているのは、直接評価するとillegal guard expression呼ばわりされてしまうためです。リファレンスのGuardの項を見てみると、次のように書いてあります。
The set of valid guard expressions (sometimes called guard tests) is a subset of the set of valid Erlang expressions. The reason for restricting the set of valid expressions is that evaluation of a guard expression must be guaranteed to be free of side effects.
 確かに、ifやwhenに何らかの作用があるのは関数型言語としてはまずいのでしょうが、かなり余計なお世話です。一旦変数にしてしまえば、関数の副作用のある部分が複数回実行されることはなくなりますし、Erlangの変数は変更されない(a variable can only be bound once.)わけですから、ifやwhenから副作用を排除できる、という理屈です。そうでない場合、全く同じ条件判定を2つ並べた場合であっても、後者が実行されるような珍妙な事態に陥りかねません。ただ、いずれにしても言語側で規制すべき事柄ではない気がしてなりません。それとも最適化(メモ化など)を行う上で都合が悪いのでしょうか。
 今回書いたfilter/2は高階関数ですから、呼び出す際には関数を渡さなくてはなりませんが、関数型言語のお約束通り、Erlangもラムダをサポートしています。
1> c(blog).
{ok,blog}

2> blog:filter(fun(X) -> X > 5 end , [1 , 9 , 2 , 8 , 3 , 7]).
[9,8,7]
 ラムダの書き方も手続き型に近いので、とっつきやすいのではないでしょうか。
 なかなか面白い言語ですし、エリクソン他で使用されている実績もありますので、普及して欲しい言語の1つです。
カテゴリ [開発魔法][社会問題][経済・知的財産] [トラックバック 0][コメント 0]

開発者解放裁判
2009/10/11(Sun)23:32:25
 Winnyの開発者が著作権法違反で逮捕され、地裁で有罪判決を受けていた問題で、高裁は逆に著作権法違反のほう助を否定し、無罪判決を言い渡しました。判決では「ほう助の成立には、侵害する者が出る可能性があると認識していただけでなく、ソフトを侵害の用途で使用するようインターネット上ですすめていることが必要」であるとした上で、「ほう助を原審のように認めると、ソフトが存在する限り無限に刑事責任を問われることになるので、罪刑法定主義の観点から慎重に判断しなければならない」と明確に指摘し、被告人の行為はほう助に当たらないと結論しました。
 私も他人事ではありませんので、かねてからこの裁判の行方には強い関心を持ってきましたが、ようやく当然の判決が下ったと言うよりありません。判決の骨子にも「罪刑法定主義」の言葉が現れているように、原判決は法の理念を逸脱した判決であるとさえ言っても過言ではなく、破棄するのは当たり前です。
 いざとなればフライパンでもレンガでも凶器になるのと同様、この世に存在するプログラムやソースコードのほとんどは、何らかの形で悪用される可能性を秘めています。FTPやメールソフトでもファイルの違法なやり取りは可能ですし、暗号化技術は違法なファイルのやり取りの隠蔽に用いられる恐れがあります。ファイル操作やループ処理のような普遍的な操作でさえ、ウイルス作成や電算機破壊に流用できます。
 もし「違法行為に使用できる」プログラムを作ったとして、それで逮捕されるのであれば、それこそ木の枝が存在するだけで「凶器になる」と称して逮捕されるような次元の話です。罪刑法定主義どころか、都合の悪い開発者は即座に逮捕できてしまいます。世の中におよそ絶対に悪用できないプログラムやソースコードが存在しない以上、いかなるプログラムであっても「著作権法違反のほう助の疑いがある」「電算機を破壊する疑いがある」と称すれば、逮捕が可能となってしまうのです。
 判決中で「被告は著作権侵害の可能性を認識はしていたが、著作権侵害の用途で使うようすすめていたとはいえない」と指摘されている通り、被告人に著作権侵害の可能性の認識があったのは確かでしょう。しかしながら、もし可能性を認識していただけで逮捕されてしまうのであれば、何らかの通信ソフトに「著作権法を遵守してください」と注意書きをしたり、CGIプログラムに「サーバーに過剰な負荷をかけないように使用してください」と注意書きをする行為は、それぞれ開発者が著作権法違反や電算機破壊の可能性を認識していたことになりますので、それを口実に逮捕されてしまいかねません。「認識」のみでは罪に問われないとする判断は妥当どころか、そう判断しない方が異常です。
 無論、違法行為に流用できるプログラムを作成し、それを使った違法行為を推奨していたのであれば、逮捕されても文句は言えません。しかしながら、私はWinnyの実物を見たことがないため、実際のところは分かりませんが、違法行為を推奨するどころか著作権法に違反しないよう求める注意書きがなされていたと聞いたことがあります。また、そのような注意書きが存在しなかったとしても、いちいち違法行為をしないよう注意する義務などあるわけがなく、逮捕には全く正当性がありません。常識的に考えて、この件を起訴しようという行動自体がまずもって信じられず、京都府警の私怨、あるいは裏で産業界が暗躍しているなど、何らかの事情を考えない方が困難です。裁判にしても、本来であれば一笑に付されて当然のところを、地裁で有罪判決が出た点には戦慄すら覚えます。
 今回の高裁判決は、そもそも至極当然の判決ですから「評価する」と表現するのも変ですが、ひとまず評価できます。これが判例となれば、恣意的な法運用で「都合の悪い」開発者が逮捕され、その方面の技術も封印されてしまう可能性は低くなりますし、著作権利権者が何らかの技術やその開発者を消し去るための手段として、この種の法を曲解して使用することもできなくなります。
 B-CASといい、JASRACといい、CCCDといい、昨今の著作権利権者の暴走には目に余るものがあります。利用者に不便を押し付けたり、アーティストの意向を完全無視したり、技術の革新を遅らせたりと、利用側ばかりか作成側、ひいては日本中に不利益を与えているのではないかとすら考えざるを得ないほどです。今回の判決が、開発者を戦慄・萎縮させる状況の打破だけにとどまらず、著作権利権者の暴走の歯止めの一助となれば、これほど良いことはありません。

 AdaICのドキュメントのInterfacing with COBOLの項には、AdaからCOBOLのファイルを読み込んで扱っているらしいサンプルがあります。
with Interfaces.COBOL;
with COBOL_Sequential_IO; -- Assumed to be supplied by implementation
procedure Test_External_Formats is
(中略)
end Test_External_Formats;
 ここではCOBOL_Sequential_IOなるものが使用されていますが、そのようなものはAdaの標準ライブラリには存在しません。それもそのはず、長々とコードがあると見落としてしまいがちですが、しっかり「Assumed to be supplied by implementation」と書いてあるのです。それにしても、書き方が少々詩的ではないでしょうか。英語が理解できない私にはつらいです。「もしあなたがこれを使用することを望むなら、それを実装しなさい」とでも書いてくれれば、少しは分かりやすそうなのですが。
 それでは、COBOL_Sequential_IOなるものは実装できるのでしょうか。Adaのプロであれば考えるまでもなく実装してしまいそうですが、残念ながら私は不得手です。しかしながら、以前にAdaのIOは一通り扱ってみたことがあり、その時の経験からすれば実装できそうでしたので、試しに書いてみました。
 まずCOBOLでSEQUENTIAL形式のテストファイルを生成し、
IDENTIFICATION DIVISION.
	PROGRAM-ID. COBOL_FILE.

ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT FTEST ASSIGN TO 'ada_test'
				ORGANIZATION IS SEQUENTIAL
				ACCESS MODE IS SEQUENTIAL.

DATA DIVISION.
	FILE SECTION.
		FD FTEST.
			01 DTEST.
				03 DID PIC 9(4).
				03 DFNAME PIC X(16).
				03 DLNAME PIC X(16).

PROCEDURE DIVISION.
	MAIN-PARAGRAPH.
		OPEN OUTPUT FTEST

		MOVE 1 TO DID
		MOVE 'Ada' TO DFNAME
		MOVE 'Lovelace' TO DLNAME
		WRITE DTEST

		MOVE 2 TO DID
		MOVE 'Haskell' TO DFNAME
		MOVE 'Curry' TO DLNAME
		WRITE DTEST

		MOVE 3 TO DID
		MOVE 'Agner' TO DFNAME
		MOVE 'Erlang' TO DLNAME
		WRITE DTEST

		CLOSE FTEST.
 AdaのDirect_IOを使って読み込んでみます。
with Interfaces.COBOL;
use Interfaces.COBOL;

with Ada.IO_Exceptions , Ada.Direct_IO;
use Ada.IO_Exceptions;

with Ada.Text_IO;
use Ada.Text_IO;

with Ada.Characters.Latin_1;
use Ada.Characters;

procedure Ada_File is
	type lang is record
		id : Alphanumeric(1..4);
		name : Alphanumeric(1..16);
		ulang : Alphanumeric(1..16);
	end record;

	package Lang_IO is new Ada.Direct_IO(lang);
	use Lang_IO;

	file : Lang_IO.File_Type;
	data : lang;

begin
	Open(file , In_File , "ada_test");

	while not End_Of_File(file) loop
		Read(file , data);

		Put_Line(To_Ada(data.id) & Latin_1.HT & To_Ada(data.name) &
			Latin_1.HT & To_Ada(data.ulang));
	end loop;

	Close(file);
end Ada_File;
 結果、上手く動作してしまいました。そもそもあのサンプル、COBOL_Sequential_IOをwithするのではなく、Direct_IOを実体化して使用した方が分かりやすかったのではないでしょうか。
 ところが、これにも落とし穴があります。データが固定長であれば特に問題はありませんが、可変長の場合はデータが変化してしまいます。
IDENTIFICATION DIVISION.
	PROGRAM-ID. COBOL_FILE.

ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT FTEST ASSIGN TO 'ada_test'
				ORGANIZATION IS SEQUENTIAL
				ACCESS MODE IS SEQUENTIAL.

DATA DIVISION.
	FILE SECTION.
		FD FTEST.
			01 DTEST.
				03 DID PIC 9(4).
				03 DLEN PIC 9.
				03 MEMBERS OCCURS 1 TO 3 DEPENDING ON DLEN.
					05 MNAME PIC X(16).

PROCEDURE DIVISION.
	MAIN-PARAGRAPH.
		OPEN OUTPUT FTEST

		MOVE 1 TO DID
		MOVE 1 TO DLEN
		MOVE 'Ada' TO MNAME(1)
		WRITE DTEST

		MOVE 2 TO DID
		MOVE 2 TO DLEN
		MOVE 'Haskell' TO MNAME(1)
		MOVE 'Erlang' TO MNAME(2)
		WRITE DTEST

		CLOSE FTEST.
 この場合、データの長さは可変ですので、ファイルの各データの先頭に32ビットのビッグエンディアンのデータが付加されます。可変でない場合は何も付加されないくせに(OpenCOBOLの場合。他のCOBOLは不明)、全く厄介な仕様です。もし可変長のSEQUENTIALデータを読み取りたいのであれば、まずデータ長4バイトを読み取って確認し、それに応じたバイト数を読み込まなくてはなりません。
 かなり泥臭くはなりましたが、とりあえず実装してみました。最初に以下のCOBOLプログラムでファイルを作っておいて、
IDENTIFICATION DIVISION.
	PROGRAM-ID. COBOL_FILE.

ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT FTEST ASSIGN TO 'ada_test'
				ORGANIZATION IS SEQUENTIAL
				ACCESS MODE IS SEQUENTIAL.

DATA DIVISION.
	FILE SECTION.
		FD FTEST.
			01 DTEST.
				03 DID PIC 9(4).
				03 DNAME PIC X(16).
				03 DLEN PIC 9.
				03 MEMBERS OCCURS 1 TO 5 DEPENDING ON DLEN.
					05 MID PIC 9(4).
					05 MNAME PIC X(16).

PROCEDURE DIVISION.
	MAIN-PARAGRAPH.
		OPEN OUTPUT FTEST

		MOVE 1 TO DID
		MOVE '資産' TO DNAME
		MOVE 3 TO DLEN

		MOVE 1 TO MID(1)
		MOVE '現金' TO MNAME(1)

		MOVE 2 TO MID(2)
		MOVE '当座預金' TO MNAME(2)

		MOVE 3 TO MID(3)
		MOVE '売掛金' TO MNAME(3)

		WRITE DTEST

		MOVE 2 TO DID
		MOVE '負債' TO DNAME
		MOVE 2 TO DLEN

		MOVE 4 TO MID(1)
		MOVE '買掛金' TO MNAME(1)

		MOVE 5 TO MID(2)
		MOVE '未払金' TO MNAME(2)

		WRITE DTEST

		MOVE 3 TO DID
		MOVE '費用' TO DNAME
		MOVE 1 TO DLEN

		MOVE 6 TO MID(1)
		MOVE '仕入' TO MNAME(1)

		WRITE DTEST

		CLOSE FTEST.
 それをAdaで読み込みます。
with Interfaces.COBOL;
use Interfaces.COBOL;

with Ada.IO_Exceptions , Ada.Streams.Stream_IO;
use Ada.IO_Exceptions , Ada.Streams , Ada.Streams.Stream_IO;

with Ada.Text_IO , Ada.Integer_Text_IO;
use Ada.Text_IO , Ada.Integer_Text_IO;

with Ada.Characters.Latin_1;
use Ada.Characters;

with Ada.Unchecked_Conversion;

procedure Ada_File is
  type Member is record
    id : Numeric(1..4);
    name : Alphanumeric(1..16);
  end record;

  type Member_Array is array(Integer range <>) of Member;

  type Content is record
    id : Numeric(1..4);
    name : Alphanumeric(1..16);
    len : Numeric(1..1);
    members : Member_Array(1..5);
  end record;

  function Get_Size(stream : Stream_Element_Array)
    return Stream_Element_Offset is
    result : Integer := 0;
  begin
    for i in 1..4 loop
      result := result ** 8 + Integer(stream(Stream_Element_Offset(i)));
    end loop;

    return Stream_Element_Offset(result);
  end Get_Size;

  type ID_Type is delta 1.0 digits 4;
  package Decimal_ID is new Decimal_Conversions(ID_Type);

  type Length_Type is delta 1.0 digits 1;
  package Decimal_Length is new Decimal_Conversions(Length_Type);

  file : Ada.Streams.Stream_IO.File_Type;
  size : Stream_Element_Offset := 0;
  offset : Stream_Element_Offset;

  data : Content;

begin
  Open(file , In_File , "ada_test");

  begin
    while not End_Of_File(file) loop
      -- サイズを読み取る
      declare
        s : Stream_Element_Array(1..4);
      begin
        Read(file , s , offset);
        size := Get_Size(s);
      end;

      -- サイズに応じて処理
      declare
        subtype COBOL_Record_Stream_Element_Array is 
          Stream_Element_Array(1..size);
        function Conversion is new Ada.Unchecked_Conversion(
          COBOL_Record_Stream_Element_Array , Content);
        d : COBOL_Record_Stream_Element_Array;
      begin
        Read(file , d , offset); 
        data := Conversion(d);
      end;

      declare
        occurs : Integer := Integer(Decimal_Length.To_Decimal(
          data.len , Unsigned));
      begin
        Put(Integer(Decimal_ID.To_Decimal(data.id , Unsigned)));
        Put_Line(Latin_1.HT & To_Ada(data.name));

        for i in 1..occurs loop
          Put(Latin_1.HT);
          Put(Integer(Decimal_ID.To_Decimal(data.members(i).id , Unsigned)));
          Put_Line(Latin_1.HT & To_Ada(data.members(i).name));
        end loop;
      end;
    end loop;
  exception
    when Ada.Streams.Stream_IO.End_Error =>
      Put_Line("ファイルを最後まで読み込みました。");
  end;

  Close(file);
end Ada_File;
 まともなAda使いの方であれば、絶対にもっとまともなコードを書くはずですが、私ではこの程度が限界でした。結果は以下の通りです。
1	資産
	1	現金
	2	当座預金
	3	売掛金
2	負債
 	4	買掛金
	5	未払金
3	費用
	6	仕入
 ついでにRELATIVEファイルも処理してみます。RELATIVEファイルは「RECORD KEY * 1レコードのバイト数」によって読み取り開始位置を求める構造ですので、可変長のデータは構造上存在せず、可変長配列であってもしっかり最大長分のデータが保存されます。また、SEQUENTIALのように順次読み取るのには向いておらず、ランダムアクセスに向いた形式です。
 他のCOBOL処理系での動作は不明ですが、少なくともOpenCOBOLの場合、RELATIVEファイルの先頭4バイトにはレコードサイズが格納され、その後にデータが格納されます。ところが、SEQUENTIALの場合と違い、サイズデータはなぜかリトルエンディアンです(多くの言語はリトルエンディアンであるため、こちらの方が扱いやすいとはいえますが)。また、存在しないレコードや削除されたレコードのサイズには0が格納されます。ただし、サイズがいかなる値であれ、1レコードの占有サイズは変わりません
 こちらはDirect_IOで読めそうですので、Direct_IOを使って処理を書いてみました。まず以下のCOBOLプログラムを実行し、ファイルを作成しまして、
IDENTIFICATION DIVISION.
	PROGRAM-ID. COBOL_FILE.

ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT FTEST ASSIGN TO 'ada_test'
				ORGANIZATION IS RELATIVE
				ACCESS MODE IS RANDOM
				RECORD KEY IS DID.

DATA DIVISION.
	FILE SECTION.
		FD FTEST.
			01 DTEST.
				03 DID PIC 9(4).
				03 DGENRE PIC X(4).
				03 DTITLE PIC X(64).
				03 DDESCRIBE PIC X(128).

PROCEDURE DIVISION.
	MAIN-PARAGRAPH.
		OPEN OUTPUT FTEST

		MOVE 1 TO DID
		MOVE 'ARPG' TO DGENRE
		MOVE 'コボル・ハンター 4つのディヴィジョン' TO DTITLE
		MOVE '世界の原理である4つのディヴィジョンをめぐる、' &
		'魔界の小鬼コボルと人類の対立を描いたARPG。' TO DDESCRIBE
		WRITE DTEST

		MOVE 2 TO DID
		MOVE 'ARPG' TO DGENRE
		MOVE 'コボル・ハンター 絶滅への道' TO DTITLE
		MOVE '前回より四半世紀後。コボルの生息域は' &
		'大幅に狭まり、絶滅の危機に瀕していた。' TO DDESCRIBE
		WRITE DTEST

		MOVE 3 TO DID
		MOVE 'RPG' TO DGENRE
		MOVE 'プリンセス エイダ' TO DTITLE
		MOVE '産業革命の時代を生きる、貴族の娘エイダの物語。' TO DDESCRIBE
		WRITE DTEST

		MOVE 4 TO DID
		MOVE 'RPG' TO DGENRE
		MOVE 'キャメルエイジ' TO DTITLE
		MOVE '中世エジプトを舞台にした、交易・冒険・戦闘RPG。' &
		'名作MLからシステムの多くを引き継いだ。' TO DDESCRIBE
		WRITE DTEST

		MOVE 5 TO DID
		MOVE 'SLG' TO DGENRE
		MOVE 'モナドロジー・モナド' TO DTITLE
		MOVE '「状態」を制御する力「モナド」の使い方がカギの' &
		'本格的な戦略シミュレーションRPG。' TO DDESCRIBE
		WRITE DTEST

		MOVE 6 TO DID
		MOVE 'TBL' TO DGENRE
		MOVE 'パイソン・アンド・ラダー' TO DTITLE
		MOVE '最大4人対戦が可能な、外国のすごろくが' &
		'モデルのテーブルゲーム。' TO DDESCRIBE
		WRITE DTEST

		MOVE 7 TO DID
		MOVE 'PZL' TO DGENRE
		MOVE '電話交換手アーラン' TO DTITLE
		MOVE '電話交換手をテーマとした、' &
		'斬新でユニークなパズルゲーム。' TO DDESCRIBE
		WRITE DTEST

		MOVE 8 TO DID
		MOVE 'SIM' TO DGENRE
		MOVE 'カフェベイブ' TO DTITLE
		MOVE '小さなテナント店「カフェベイブ」を' &
		'世界一のコーヒー店に成長させてください。' TO DDESCRIBE
		WRITE DTEST

		CLOSE FTEST

*		一部のレコードを削除
		OPEN I-O FTEST

		MOVE 1 TO DID
		DELETE FTEST

		MOVE 5 TO DID
		DELETE FTEST

		CLOSE FTEST.
 これをAdaで読み取ります。なお、上記サンプルデータにCOBOLへの皮肉が入っていることは言うまでもありません。
with Interfaces.COBOL;
use Interfaces.COBOL;

with Ada.Direct_IO;

with Ada.Text_IO , Ada.Integer_Text_IO;
use Ada.Text_IO , Ada.Integer_Text_IO;

with Ada.Characters.Latin_1;
use Ada.Characters;

with Ada.Strings.Fixed;
use Ada.Strings , Ada.Strings.Fixed;

procedure Ada_File is
  -- レコードサイズ型(32ビット)
  type Size_Number is mod (2 ** 32);

  -- COBOL のレコードに対応するレコード
  type Content is record
    id : Numeric(1..4);
    genre : Alphanumeric(1..4);
    title : Alphanumeric(1..64);
    describe : Alphanumeric(1..128);
  end record;

  -- RELATIVE レコードに対応するレコード
  type Relative_Content is record
    size : Size_Number;
    data : Content;
  end record;

  package Relative_IO is new Ada.Direct_IO(Relative_Content);
  use Relative_IO;

  type ID_Type is delta 1.0 digits 4;
  package Decimal_ID is new Decimal_Conversions(ID_Type);

  file : Relative_IO.File_Type;
  record_data : Relative_Content;

  -- 末尾のスペースをすべて削除する関数
  function Text_Triming(str : String; c : Character := ' ')
    return String is
  begin
    return Head(str , Index_Non_Blank(str , str'Last , Backward));
  end Text_Triming;

begin
  Open(file , In_File , "ada_test");

  for i in 1..8 loop
    begin
      Put("Record Key: ");
      Put(i);
      New_Line;

      Read(file , record_data , Relative_IO.Positive_Count(i));

      -- size = 0 の場合はデータがない
      if record_data.size /= 0 then
        Put(Integer(Decimal_ID.To_Decimal(record_data.data.id , Unsigned)));
        Put_Line(Latin_1.HT & To_Ada(record_data.data.genre) & Latin_1.HT &
          Text_Triming(To_Ada(record_data.data.title)));
        Put_Line(Latin_1.HT & Text_Triming(To_Ada(record_data.data.describe)));
      else
        raise Relative_IO.End_Error;
      end if;
    exception when Relative_IO.End_Error =>
      Put_Line(Latin_1.HT & "データがありません。");
    end;
  end loop;

  Close(file);
end Ada_File;
 全くスマートではありませんが、ひとまず無事にファイルが読み込めました。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 2]

ウソ九百
2009/10/04(Sun)17:48:03
 2016年のオリンピック開催地がブラジルのリオデジャネイロに決定しました。オリンピックが南米で開催されるのは、(メキシコを含めなければ)これが初めてとなります。当初からリオデジャネイロが優勢との見方は強く、また私は経済的側面などから同都市がもっともふさわしいと考えていましたが、投票では番狂わせが生じたとはいえ、大方の予想通りの結果となりました。
 同都市の他にはマドリード、シカゴ、東京が候補となっていましたが、有力な対抗馬とみられていたシカゴは早々に脱落、次の投票では東京もあえなく落選し、本命とはみなされていなかったマドリードが意外な健闘を見せていましたが、治安や整備への不安を補って余りある期待により、見事にリオデジャネイロが決戦を制したようです。
 今回の選定で、本気で東京が選ばれるなどと考えていたのは、せいぜい石原氏程度ではないでしょうか。オバマ氏のテコ入れにもかかわらず敗退したシカゴのおかげで、最下位の汚名こそ免れたとはいえ、これほど勝利を見込めない選考もありません。結局、日本は誘致に無駄な費用と労力を費やしてしまったことになります。
 私はオリンピックというものに全く興味がないため、以下では基本的に経済的側面から問題を論じてみます。結果は最初からほぼ分かりきっていたとはいえ、まかり間違って東京が勝ってしまわなくてよかったとしか言いようがありません。また、リオデジャネイロが開催地に決定されたのも良いことです。
 日本が高度経済成長を遂げようかという1964年、東京でオリンピックが開催されたことがありました。このタイミングでの開催はまさに大正解と言えるもので、戦後復興の時代を脱却し、躍進しようとする日本の国威と知名度を上昇させる一助になったのは間違いありません。このようなタイミングでのオリンピック誘致であれば、私もそれに反対する理由はありませんし、コストを補って余りある有形無形の利益が得られることでしょう。
 ところが、日本はすでに高度経済成長を終え、先細りさえ心配される時代に入ってきました。今の時代にオリンピックなどを行ったとしても、今さら諸外国へのアピールにはなりませんし、交通網を整備すれば赤字となり、祭りの後には余計なハコモノが残るだけです。一時的なオリンピック景気は訪れたとしても、せいぜい一過性のものに過ぎず、景気・雇用回復の役には立ちません。今の日本の状況下で誘致に成功したとしても、まともな利益は得られないのです。
 これが昔の日本であったり、リオデジャネイロのような国であれば、また話は違ってきます。オリンピックに備えて整備した交通網は貴重なインフラとなり、オリンピックがもたらす需要は経済成長を生み出します。ブラジルはBRICsの一国でもあり、21世紀中の発展が期待できる国ですので、まさに非常に良いタイミングでの開催といえるでしょう。それを、オリンピックを開催したところで効果に期待できない状況でありながら、日本がわざわざ大都市抱えてしゃしゃり出て、経済成長を控えている国からオリンピック開催権を取り上げようともくろむとは、一体何を考えているのでしょうか。
 今後の日本は国内需要が先細り傾向とあって、政府内外には日本の観光産業の充実を模索する動きもあるようですが、その戦略の一環としてオリンピックを誘致するなどの想定があるのであれば、それも手段の1つとして考えられます。しかしながら、今回のようにほとんど気分の問題でオリンピックを誘致している限り、仮にオリンピックの開催権を獲得したとしても、単に負の遺産を残すだけの結果となるでしょう。

 非嫡出子が遺産分配などで差別を受けている問題で、最高裁はまたも民法の規定を合憲の判断を下しました。4人中3人の多数意見でしたが、裁判官のうち今井氏は「嫡出子には何の責任もない」として違憲と判断し、また竹内氏も「相続時は合憲だが、現時点では違憲の疑いが極めて強い」として、当時でこそ合憲であったものの、もし現在において同様の問題が発生した際には、違憲の可能性が高いとの意見を示しました。非嫡出子差別問題に関しては、今後とも問題視されていくことはあれ、差別が適切との見解が広まる状況はあまり考えられませんので、このまま一切の立法が行われなかったとしても、いずれは違憲となる可能性が十分にあるのは確かです。
 遺産相続の上で非嫡出子を不平等に扱う規定は、民法900条4号にて次のように定められています。
民法第九百条
同順位の相続人が数人あるときは、その相続分は、次の各号の定めるところによる。
(中略)
四 子、直系尊属又は兄弟姉妹が数人あるときは、各自の相続分は、相等しいものとする。ただし、嫡出でない子の相続分は、嫡出である子の相続分の二分の一とし、父母の一方のみを同じくする兄弟姉妹の相続分は、父母の双方を同じくする兄弟姉妹の相続分の二分の一とする
(太字は引用者による)
 すなわち、非嫡出子は嫡出子の1/2の遺産しか受け取れないものとされています。最近でこそ非嫡出子や事実婚夫婦といった人々の権利も保障されるようになってきましたが、かつては社会からも法からも阻害された扱いとなっており、この種の規定はその名残といえるでしょう。
 なお、上記規定が最初に合憲と判断されたのは1995年7月5日で、上記900条4号但し書きの規定は憲法14条に反するものではなく、合憲との判断が下されています。
憲法第十四条
すべて国民は、法の下に平等であつて、人種、信条、性別、社会的身分又は門地により、政治的、経済的又は社会的関係において、差別されない。
 判決文の中でも少々興味深いのが、以下の部分です。
 本件規定の立法理由は、法律上の配偶者との間に出生した嫡出子の立場を尊重するとともに、他方、被相続人の子である非嫡出子の立場にも配慮して、非嫡出子に嫡出子の二分の一の法定相続分を認めることにより、非嫡出子を保護しようとしたものであり、法律婚の尊重と非嫡出子の保護の調整を図ったものと解される。これを言い換えれば、民法が法律婚主義を採用している以上、法定相続分は婚姻関係にある配偶者とその子を優遇してこれを定めるが、他方、非嫡出子にも一定の法定相続分を認めてその保護を図ったものであると解される。
 現行民法は法律婚主義を採用しているのであるから、右のような本件規定の立法理由にも合理的な根拠があるというべきであり、本件規定が非嫡出子の法定相続分を嫡出子の二分の一としたことが、右立法理由との関連において著しく不合理であり、立法府に与えられた合理的な裁量判断の限界を超えたものということはできないのであって、本件規定は、合理的理由のない差別とはいえず、憲法一四条一項に反するものとはいえない。
 すなわち、非嫡出子は差別されるのが当たり前で、遺産を嫡出子の1/2だけ受け取れるのは、非嫡出子を差別ではなく保護したものであるというのです。確かに、立法当時の社会情勢を考えれば、もっともらしい意見ではあります。
 しかしながら、社会の思想は大きく変化しました。立法当時の考え方がどうあれ、今では「非嫡出子の遺産は1/2」との規定はどう見ても差別でしかありません。規定に賛成している人であっても、「民法が法律婚主義を定める以上、非嫡出子が嫡出子と比べて不利益をこうむるのはやむを得ない」と主張するならまだしも、「非嫡出子が嫡出子の1/2の遺産を受け取るのは、非嫡出子を保護したものである」と主張する人はほとんど存在しないでしょう。
 なお、同規定は以前より修正の必要性が議論されており、私もかねてから修正が必要と主張してきましたが、自民党政権下では慎重な意見が多く、実現の見通しが立たないままとなっていました。しかしながら、民主党政権の千葉氏は見直しに積極的な姿勢を見せており、修正される可能性が出てきています。
 それにしても、なぜ自民党は意味不明な理由でこの種の改正を拒むのでしょうか。今回の民法900条問題に限らず、772条問題では「性道徳が乱れるから」改正に反対し、戸籍を得られぬ子は公的な救済を受けられず、夫婦別姓には「家庭の一体感が損なわれるから」反対し、代理出産問題では原則論を繰り返すばかりで、現に存在する子の存在は宙に浮かせたままという有様です。このような意味不明な政党がよく政権を取っていたものだと感心するばかりです。
 無論、嫡出子らの権利を守るために900条は改正すべきでないとしたり、元配偶者の権利を守るために772条を残すべきとしたり、何らかの具体的な問題があるから夫婦別姓は行うべきでないとする意見は尊重しますし、決して否定できるものではありません。改正の代償として誰かの権利が損なわれるのであれば、十分な検証が必要なのは当然です。もし改正によって得られる利益や人権より、損なわれる利益や人権の方が大きいことが証明されれば、私も改正反対に回ることを否定しません。
 しかしながら、自民党の意味不明な自称保守派はといえば、自分の価値観を絶対化した意味不明な道徳とやらを理由に、何の罪もない非嫡出子への相続差別を容認したり、性道徳とやらを理由に、何の罪もない子が戸籍を持てなかったり、正しくない戸籍を持たなくてはならなくなったりする状態を強い、家庭の一体感などという極めて抽象的かつ根拠のない言い分によって夫婦別姓に反対したり、しまいには子の人権を「人質」にして代理出産をけん制する始末です。このような意見は尊重するどころか、まじめに論じる価値すらありません。本人らの意思である夫婦別姓はともかく、900条、772条、代理出産に対する「道徳」なる言い分は、いずれも親の責任(これ自体、単に「道徳とやらを主張する議員が好ましくないと考える」行為に抵触した責任であって、責任を取らされる合理的理由はない)を、何の落ち度もない子に押し付けているものである点が共通しており、全く正当性がありません。
 このまま900条問題を放置したとしても、いずれは違憲判決が出るのみでしょう。民主党政権には一刻も早い900条改正を期待したいところです。

 前回のGNADEでは散々Cとのインターフェイスに泣かされましたが、せっかくGNATとOpenCOBOLの両方を持っているのですから、COBOLとのインターフェイスも行ってみました。
 Adaのマニュアルに存在するInterfacing with COBOLでは、AdaからCOBOLを呼び出すことを前提としており、実際に結構色々な操作ができるようですが、ひとまずCOBOLからAdaを呼び出す実装を。どこまで正しく動くのか定かではありませんが、以下の手順でテストプログラムは何とか動作しましたので、とりあえず覚書としておきます。ゆえに正確性は一切保証できません。Adaプログラムの*.oファイルを使用する方法と、DLLを使用する方法の両方を行ってみました。

1.Adaプログラムを書く
 COBOLから呼び出すAdaプログラムを作成し、呼び出したい関数・プロシージャをpragma Exportします。
-- cobol_ada_a.ads
package COBOL_Ada_A is
	procedure Hello;

	pragma Export(COBOL , Hello , "Hello");
end COBOL_Ada_A;
 Helloプロシージャはメッセージを表示するだけの単純な実装としました。
-- cobol_ada_a.adb
with Ada.Text_IO;

package body COBOL_Ada_A is
	procedure Hello is
	begin
		Ada.Text_IO.Put_Line("Hello Ada!");
	end Hello;
end COBOL_Ada_A;
2.COBOLプログラムを書く
 以下、行番号をいちいちつけていては読みにくい上に不便ですので、フリースタイルで書いています。OpenCOBOLでは-freeオプションでコンパイルできます。あるいはタブをスペース2つに変換し、行番号をつけても構いません。
IDENTIFICATION DIVISION.
	PROGRAM-ID. COBOL_ADA_C.

PROCEDURE DIVISION.
	MAIN-PARAGRAPH.
		CALL 'adainit'
		CALL 'Hello'
		CALL 'adafinal'.
 adainit及びadafinalはAdaプログラムを呼び出す際の「お約束」であるらしく、adainitなしにCALLしてみたところ、プログラムが落ちました。ここで必要な初期化を行っているのでしょう。

 ここから、*.oファイルを生成する場合とDLLを使用する場合で手順が分かれます。まずは*.oファイルを使用する場合より。やり方が全く分からず投げ出しそうになりましたが、OpenCOBOL FAQ#Can OpenCOBOL Interface With Adaを発見したため、何とか作成できました。

A.「*.o」ファイルを生成・使用する場合
3A.Adaプログラムのコンパイルとgnatbind
 Adaの機能を利用するのに必要な部品は、すべてgnatbindが用意してくれるようです。
gnatmake -x cobol_ada_a.adb
gnatbind -n cobol_ada_a
gnatmake -x b~cobol_ada_a.adb
4A.COBOLソースのコンパイル
 コンパイル時にはlibgnat.dll(私の環境ではlibgnat-2007.dllなる名前になっていました。gnatのbinディレクトリに入っています)が必要です。以下、DLLをカレントディレクトリに置いた場合のコマンドです。-L.\の部分を変更すれば、ディレクトリの指定が可能です。-lgnatの部分はDLLの名前にあわせて変更(libgnat-2007なら-lgnat-2007または-llibgnat-2007。libは省略できる模様)します。
cobc -free -x -lgnat -L.\ cobol_ada_c.cbl cobol_ada_a.o b~cobol_ada_a.o
 私の環境では、これで無事にexeファイルが出力され、動作してくれました。

B.DLLを使用する場合
 続いてDLLを使用する方法も行ってみます。作成の際にはUsing library with Open COBOL(日本語)に大変お世話になりました。深くお礼申し上げます。

3B.DLL作成のためのdefファイルの作成
 エクスポートする関数名の一覧を記述します。ここではcobol_ada_a.defの名前で保存しました。名前は任意で構いませんが、Adaのファイル名に合わせない場合は、gnatdllでオプション指定が必要となります。
LIBRARY COBOL_Ada_A
EXPORTS
	Hello
	adainit
	adafinal
4B.gnatmakeとgnatdll
 Adaソースをコンパイルし、DLLを作成します。
gnatmake -x cobol_ada_a.adb
gnatdll -d cobol_ada_a.dll cobol_ada_a.ali
5B.COBOLソースのコンパイル
 *.oファイルを使ってコンパイルした時と同じく-lgnatが必要となりますが、今回はDLLファイルからAdaプログラムを呼び出そうとしていますので、そちらのDLLの指定も必要です。-lgnat及び-Lオプションに関しては、手順4Aと同様です。
cobc -free -x -lgnat -lcobol_ada_a -L.\ cobol_ada_c.cbl
6B.COB_PRE_LOAD環境変数の設定
 COBOLでは基本的に1ソースファイルが1つのプログラムとなるためか、このままではCALL 'adainit'に反応してadainit.dllなるファイルを探しに行ってしまいます。COBOL的には正しい動作でも、今回のように他の言語とやり取りしたい場合には困ります。
 上記で述べたサイト様「Using library with Open COBOL」にも書いてありますが、これを避けるにはDLLの名前をadainit.dllにしてしまうか、COB_PRE_LOAD環境変数で強制的にライブラリを読み込ませるしかありません。前者では自由が利きませんので、後者の方法を用いるのが適切そうです。
set COB_PRE_LOAD=cobol_ada_a
 私の環境では、これで無事にexeファイルを実行できました。
 F22戦闘機やボーイング機を動かしている言語だけに、Adaで数学計算の処理を実装しておいて、COBOLから呼び出してみても面白いかもしれません(これらにしても、実はAdaからCの数学ライブラリを呼び出しているのかもしれませんが)。なお、COBOL文字列をTo_Adaで処理したりすると、
undefined reference to `_Unwind_Resume'
 なるエラーが出たりしますが、その際にはGNATのbinディレクトリからlibgcc_s.dllを持ってきて、cobcに-lgcc_sオプションを指定すれば、問題なくコンパイルできます。

 今度は逆にAdaからCOBOLを呼び出してみます。cobcは-xオプションをつけなければ勝手にDLLを吐き出してくれますし、共有したい変数は単にLINKAGE SECTIONに書いてUSINGを使えばよく、AdaにはCOBOLとのインターフェイス機能が標準で組み込まれていますので、手順はCOBOLからAdaを呼ぶより簡単です。それにしても、AdaとCOBOLとは一体いかなる組み合わせなのでしょうか。片方は記憶力勝負の意味で厳しい言語で、もう片方は有名な手続き型高級言語の中でも最も難しいともされる言語とあっては、食べ合わせが良いのか悪いのか分かりません。少なくとも、JavaやC#のような軟弱な言語よりは消化に悪そうです。
 まず下準備として、以下のようなCOBOLプログラムを作成しました。
* ada_cobol_writer.cbl
IDENTIFICATION DIVISION.
	PROGRAM-ID. ADA_COBOL_WRITER.

ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT FILE-BS ASSIGN TO 'ada_cobol_bs'
				ORGANIZATION IS INDEXED
				ACCESS MODE IS DYNAMIC
				RECORD KEY IS FID.

DATA DIVISION.
	FILE SECTION.
		FD FILE-BS.
			01 FBS.
				03 FID PIC 9(4).
				03 FNAME PIC X(16).
				03 FVALUE PIC 9(16).

PROCEDURE DIVISION.
	MAIN-PARAGRAPH.
		OPEN OUTPUT FILE-BS

		MOVE 1 TO FID
		MOVE '現金' TO FNAME
		MOVE 12500000 TO FVALUE
		WRITE FBS

		MOVE 2 TO FID
		MOVE '当座預金' TO FNAME
		MOVE 304500000 TO FVALUE
		WRITE FBS

		MOVE 3 TO FID
		MOVE '備品' TO FNAME
		MOVE 265000000 TO FVALUE
		WRITE FBS

		MOVE 4 TO FID
		MOVE '売掛金' TO FNAME
		MOVE 55300000 TO FVALUE
		WRITE FBS

		MOVE 5 TO FID
		MOVE '研究開発費' TO FNAME
		MOVE 6680000 TO FVALUE
		WRITE FBS

		MOVE 6 TO FID
		MOVE '社債発行差金' TO FNAME
		MOVE 450000 TO FVALUE
		WRITE FBS

		CLOSE FILE-BS.
 これを-xオプションつきでコンパイルし、出力されたexeファイルを実行して、データを作成しておきます。OpenCOBOLであれば、ada_cobol_bsファイルが作成されるはずです。
 次いで、そのファイルを読み込むCOBOLプログラムを作成します。
* ada_cobol_reader.cbl
IDENTIFICATION DIVISION.
	PROGRAM-ID. Ada_COBOL_Reader.

ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT FILE-BS ASSIGN TO 'ada_cobol_bs'
				ORGANIZATION IS INDEXED
				ACCESS MODE IS DYNAMIC
				RECORD KEY IS FID.

DATA DIVISION.
	FILE SECTION.
		FD FILE-BS.
			01 FBS.
				03 FID PIC 9(4).
				03 FNAME PIC X(16).
				03 FVALUE PIC 9(16).
	LINKAGE SECTION.
		01 LBS.
			03 LID PIC 9(4).
			03 LNAME PIC X(16).
			03 LVALUE PIC 9(16).

PROCEDURE DIVISION USING LBS.
	MAIN-PARAGRAPH.
		OPEN INPUT FILE-BS
		MOVE LBS TO FBS
		READ FILE-BS
		MOVE FBS TO LBS
		CLOSE FILE-BS.
 これを-xオプションなしでコンパイルし、DLLファイルを生成します。本当はENTRYを使って処理を分けようと考えていたのですが、実際にAdaから呼び出してみると、ENTRY自体は一応認識されているらしいものの、なぜかEXIT PROGRAMを認識してくれませんので、使い物になりませんでした。GO TOも使用してみましたが、やはり効果はありませんでした。STOP RUNではプログラム自体が終わってしまいますし、困ったものです。
 ここで作成したDLLは、以下のAdaプログラムから呼び出します。
with Ada.Text_IO , Ada.Integer_Text_IO , Ada.Strings ,
	Ada.Strings.Fixed , Interfaces.COBOL;
use Ada.Text_IO , Ada.Integer_Text_IO , Ada.Strings ,
	Ada.Strings.Fixed , Interfaces;

procedure Ada_COBOL_Exec is
	-- 小数点なし16桁の数値型
	type Value_Type is delta 1.0 digits 16;

	-- id は COBOL では 9(4) であるが
	-- ここでは Alphanumeric(1..4) を使用した
	type COBOL_BS is record
		id : COBOL.Alphanumeric(1..4);
		name : COBOL.Alphanumeric(1..16);
		value : COBOL.Numeric(1..16);
	end record;

	pragma Convention(COBOL , COBOL_BS);

	-- Value_Type と Alphanumeric(1..16) を
	-- 相互変換するパッケージを実体化
	package Value_Conversions is new COBOL.Decimal_Conversions(Value_Type);
	use Value_Conversions;

	-- cobol_init と cobol_stop_run はお約束
	procedure Ada_COBOL_Reader(bs : in out COBOL_BS);
	procedure cobol_init;
	procedure cobol_stop_run;

	pragma Import(COBOL , Ada_COBOL_Reader , "Ada_COBOL_Reader");
	pragma Import(C , cobol_init , "cob_init");
	pragma Import(C , cobol_stop_run , "cob_stop_run");

	c_bs : COBOL_BS;

	procedure Show_BS_Data(b : in COBOL_BS) is
		v : Value_Type := To_Decimal(b.value , COBOL.Unsigned);
	begin
		Put_Line(COBOL.To_Ada(b.id));
		Put_Line(COBOL.To_Ada(b.name));
		Put(Integer(v));
		New_Line;
	end Show_BS_Data;

	assets : Integer := 0;
begin
	cobol_init;

	for i in 1..6 loop
		c_bs.id := COBOL.To_COBOL(
			Tail(Trim(i'Img , Left) , 4 , '0'));
		Ada_COBOL_Reader(c_bs);
		Show_BS_Data(c_bs);
		assets := assets + Integer(To_Decimal(
			c_bs.value , COBOL.Unsigned));
		New_Line;
	end loop;

	Put_Line("合計");
	Put(assets);

	cobol_stop_run;
end Ada_COBOL_Exec;
 cobol_initとcobol_stop_runはCOBOLプログラムを呼び出す際のお約束のようで、cobol_initを呼び出さずに使おうとするとエラーが発生してしまいます(ご丁寧にもcobol_initを呼び出すよう注意してくれます。無言で落ちていたCOBOL->Adaとは大違いです)。
 残るはコンパイルと実行ですが、その際にはOpenCOBOLのbinディレクトリにあるDLL一式が必要です。また、gnatmakeではリンカにada_cobol_reader.dllを指定するのと同時に、libcob-1.dllも指定する必要があります。
gnatmake ada_cobol_exec.adb -largs -lada_cobol_reader -lcob-1
 私の環境では、これで無事にコンパイルができました。資産の勘定の合計は644430000でした。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

<-前のページ [5] [6] [7] [8] [9] [10] [11] [12] [13] 次のページ->
- Blog by yamicha.com -