2007/12/09

英語の冠詞の使い方

英語の冠詞の使い方の分かりやすい説明があったので、メモ。

http://code.nanigac.com/source/wiki/view/398
http://diary.hykw.tv/index.php/category/english/
これによると、
> a,an : インスタンス生成
> the : 既存のインスタンスへのポインタ
> 冠詞なし : クラス
と考えればよいらしい。

OOPなプログラミング言語を知っている人には
分かりやすいのでは?

2007/11/22

バイオハザード3

邦題「バイオハザード3」を観た。
これまでと同じく雰囲気はゲームのそれと同じ。
日本風のじめじめとした怖さでもなく、
いわゆるホラーという怖さでもない。
変化の激しさとでもいうのだろうか、
扉を開けると…、暗い部屋を少しずつ進むと…
何か出てきそうとつい身構えてしまう。
それがはずれのときもあれば、そうでないときもあるし、
思わぬタイミングのときもある。
そういう怖さは十分あった。

ただ、アリスの設定はどうかと思う。
なんというか、「Matrix」を髣髴とさせるというか。
観ていて、「えーそんなんありかよ」と言いたくなる。

また、最後の盛り上がりが欠けていた。
息切れしたのか一定の時間に収めようとしたのかネタ切れなのか分からんが。
次に何が起きるか簡単に読めてしまったら
「怖さ」が出ないじゃないか!!

まぁ全体的にみれば、十分面白いんじゃないかな。
少なくともゲームをやったことがある人なら。

2007/11/18

ランダムウォークで目的地にたどり着くのは何時?

複雑媒質中の平均初到達時間(First-passage time)の評価ができる一般理論が開発された.
(First-passage times in complex scale-invariant media, Nature 450, 77-80)
http://www.nature.com/nature/journal/v450/n7166/full/nature06201.html

この理論では不規則媒質(disordered media),フラクタルや
スケールフリーネットワークに適用できるらしい。

これよりも平均で早く到達するなら適当に移動するより効率が良いということが分かるわけかな。

2007/11/04

生物系でのLevy flightの存在に疑問が

ワタリアホウドリ(wandering albatross)と鹿(deer)とマルハナバチ(bumblebee)の
探索戦略がlevy flight(http://en.wikipedia.org/wiki/L%C3%A9vy_flight)に従う
との証拠に疑問が呈されている.
http://www.nature.com/nature/journal/v449/n7165/full/nature06199.html

この調査では1992年に行われた調査よりも高精度にアホウドリの飛行時間を
記録できる装置を使用している.その結果,飛行時間の確率分布が
shifted gamma distribution :
f(t)=r^s y^(s-1) e^(-ry)/Γ(s)
に従うことが示された.
指数項は,飛行時間が十分に長くなるとその確率分布が
ポアソン分布に従うことを示している.

2007/11/03

マインスイーパーのチート

WinXPのマインスイーパーのチート。

http://www.geekpage.jp/blog/?id=2006/12/17
によると、
1. マインスイーパーを起動
2. 「xyzzy」と入力
3. シフトキーを1秒以上押す。

これで爆弾のないところにマウスカーソルを持っていくと、
"デスクトップ"の左上に1ドットの白い点が表示される。
爆弾があると白い点は表示されない。

2007/10/27

近接連星系での最大の質量を持つブラックホール見つかる

太陽質量の15.65(±1.45)倍のブラックホールが近接連星系で発見された。
http://www.nature.com/nature/journal/v449/n7164/full/nature06218.html
これまでに知られている中では最大の質量のもので、
近傍銀河のMessier 33(M33)の連星系M33 X-7に存在している。
連星系を構成するもう一方の星(伴星)の質量は太陽質量の70.0±6.9倍であり、
ブラックホールはこの星の周りを3.45日周期で回っている。
ブラックホールの質量が観測できたのは、この連星系が食連星であったためである。
つまり、連星系が回転している平面をほぼ真横から観測しているということになる。

なお、単に質量の大きいブラックホールであれば他にも存在が予想されており、
例えば、銀河中心に存在していると考えられているものがある。
その質量は太陽質量の10の6乗倍から9乗倍にもなる。

2007/09/05

トランスフォーマー

ハリウッド映画のトランスフォーマーを見てきた。
内容は金のかかったコメディといえそうだ。

CGの出来はなかなかのものだし、
米軍機がいくつもでてくる。F22やAC130などなど。

ただ、ストーリーが軽い。とっても軽い。
そう感じる原因は、おそらくあのちっちゃい
ディセプトロンのロボットだろう。
動きもしゃべり方もどこかでいそうな
ノリの軽いやつだからだ。

というわけで、きれいなCGを見たければ価値があるかも。

2007/07/28

ケロミン

カエルの人形で演奏!
みょーにかわいいし、おもしろそうだが、値段が微妙…
http://www.keromin.com/

2007/07/26

本の出版

本を出版するときって、出版社に企画書を出すところから始まるらしい。
http://itpro.nikkeibp.co.jp/article/Watcher/20070723/278082

IntelがTBBをGPLで配布

Intel Threading Building Blocks がGPL v2で配布。
http://www.threadingbuildingblocks.org/

ライセンスをよくよく見てみると、GPLv2 with the runtime exception
と書いてある。テンプレートやinline展開された部分については、
GPLが伝播しないよということっぽい。

boost licenseのほうが簡単でいいな…

記事
http://itpro.nikkeibp.co.jp/article/NEWS/20070725/278194/?L=rss

2007/07/01

GPL v3 リリース

とりあえず、メモ。
http://www.gnu.org/licenses/gpl.html

特許に関する条項も入っている。

2007/06/29

フリーのXML DB

IBM社製のXMLデータベース「DB2 Express-C 9」が公開されているとのこと。
http://www.ibm.com/db2/express/

記事はここ。
http://itpro.nikkeibp.co.jp/article/COLUMN/20070531/273212/

2007/06/22

flash メモ

flash を作成するソフト「suzuka」を準備する。
http://www.cty-net.ne.jp/~uzgensho/

active scriptを使うなら、
http://www.geocities.jp/myflashsouko/flash/index4.html
が参考になる。

詳細を調べるには
http://livedocs.adobe.com/flash/8_jp/
にあるドキュメントを参考にすればいい。

2007/06/13

デスクトップ冷暖房機!?

Herman Millerの局所冷暖房装置 C2 だそうで。
http://www.itmedia.co.jp/bizid/articles/0706/12/news079.html
<引用>
社内テストでは、C2は周囲の室温が摂氏22.2度の段階からスタートし、
周囲15センチ四方の温度を44.4度まで暖め、17.8度まで冷却できたという。
</引用>

15センチかぁ、微妙だな。
装置の前方1mくらい効果があればよいのだが。

そもそも、暖房はいいとして、冷房の廃熱はいったいどこへ逃がすんだろう?
いまいち機構がわからん。

2007/05/19

逆指値注文の特許

逆指値注文の特許があるとは。

特許第3875206号

それにしても請求項の記述が長いので、文字数を調べてみた。
 請求項1:1338文字
 請求項2:1647文字

がんばったなぁ。

2007/05/15

リースの資産計上

WBSで出ていたが、08年度からリースで借りた設備が資産計上されるのだそうだ。
これじゃあリースのメリットが一つなくなるな。
リース業界も再編らしい。

2007/05/13

erlang その10

続続続ets module
ets:matchの関連関数を使ってみる。

<ets_tut5.erl>

-module(ets_tut5).
-export([test/0]).


test()->
P = ets:new(test1, [bag]),
ets:insert(P, [{a,1,r},{b,2,s},{b,3,u},{b,4,u},{c,5,u}]),
io:format("~p~n", [ets:match_object(P, {'_','$1','$2'})]),
io:format("~p~n", [ets:match_object(P, {'_','_','_'})]),
io:format("~p~n", [ets:match_object(P, {'_','_','u'})]),
ets:delete(P).


結果は次のようになる。
157> c(ets_tut5).
{ok,ets_tut5}
158> ets_tut5:test().
[{c,5,u},{b,2,s},{b,3,u},{b,4,u},{a,1,r}]
[{c,5,u},{b,2,s},{b,3,u},{b,4,u},{a,1,r}]
[{c,5,u},{b,3,u},{b,4,u}]
true

パターンに一致した要素をそのまま取得できていることが確認できる。また、ets:matchで使えた $1 や $2 は _ と同様に解釈されるようである。

次に、match_object(Tab, Pattern, Limit) と match_object(Continuation) を使ってみる。この2つの関数はPatternに一致した要素のうち、Limit個ずつ結果として受け取るために使う。ここでは、Patternに一致した要素を引数で指定した関数で処理する関数を作ってみる。
<ets_tut6>
-module(ets_tut6).
-export([test/0]).


test()->
P = ets:new(test1, [bag]),
ets:insert(P, [{a,1,r},{b,2,s},{b,3,u},{b,4,u},{c,5,u}]),
X = foreach(P, {'b','_','_'},
fun(X)->io:format("~p~n", [X]) end),
ets:delete(P),
X.


foreach(P, Pattern, Fun)->
foreach(ets:match_object(P, Pattern, 1), Fun).


foreach(X, _) when X=='$end_of_table' ->ok;


foreach({Match, Cont}, Fun)->
lists:foreach(Fun, Match),
foreach(ets:match_object(Cont), Fun).


tupleの先頭の要素が b である要素を表示するようにしたので、
199> c(ets_tut6).
{ok,ets_tut6}
200> ets_tut6:test().
{b,4,u}
{b,3,u}
{b,2,s}
ok

という結果が得られる。

2007/05/11

erlang その9

続続ets module

ets:matchを使ってみる。
この関数はパターンに一致したtupleをテーブルから取り出す。
取り出される値はtupleそのものではなく、指定したtupleの要素のリストとなる。
形式的な定義はリファレンスマニュアルをみればわかるので、使用例を示す。
<ets_tut4.erl>

-module(ets_tut4).
-export([test/0]).


test()->
P = ets:new(test1, [bag]),
ets:insert(P, [{a,1,r},{b,2,s},{b,3,u},{b,4,u},{c,5,u}]),
io:format("~p~n", [ets:match(P, {'_','$1','$2'})]),
io:format("~p~n", [ets:match(P, {'_','$2','$1'})]),
io:format("~p~n", [ets:match(P, {a,'$1','_'})]),
io:format("~p~n", [ets:match(P, {b,'_','$1'})]),
io:format("~p~n", [ets:match(P, {'$1','_',u})]),
ets:delete(P).


これを実行すると、
1> c(ets_tut4).
{ok,ets_tut4}
2> ets_tut4:test().
[[5,u],[2,s],[3,u],[4,u],[1,r]]
[[u,5],[s,2],[u,3],[u,4],[r,1]]
[[1]]
[[s],[u],[u]]
[[c],[b],[b]]
true

となる。matchの第1引数はテーブル識別子で第2引数にパターンを指定する。
最初の出力で指定したパターンは
 {'_','$1','$2'}
であるが、これはPに格納されているtupleのうち、全ての要素が任意であることを示す。
つまり、Pに記録されているtupleが全て得られる。'_'はただ任意であることを示す。
一方、'$1'や'$2'は戻り値として得たい要素であることを示している。
'$1'に指定された要素は戻り値のリストの1番目の要素に記録され、'$2'は2番目に記録される。
したがって、得られる結果は
[[5,u],[2,s],[3,u],[4,u],[1,r]]
となる。

2つ目の出力で指定したパターンは最初のものと'$1'と'$2'の位置が入れ替わっている。
これは結果が先ほどのものと順序が逆になるということであり、
[[u,5],[s,2],[u,3],[u,4],[r,1]]
が得られる。

3つ目の出力で指定したパターンは{a,'$1','_'}である。
これはtupleの最初の要素がaであるもののみ取得することを示している。
したがって、最初の要素がaであるのは{a,1,r}であり、出力結果は
2番目の要素で構成されることになっているので、結果は
[[1]]
となる。

4つ目の出力で指定したパターンは{b,'_','$1'}である。
先ほどと同様の理由で、
[[s],[u],[u]]
が得られる。

テーブルのキーでない要素でも指定することができる。
5つ目の出力ではtupleの3番目の要素を指定する。パターンは{'$1','_',u}である。
uに一致するもののうち、最初の要素を集めるので、結果は、
[[c],[b],[b]]
となる。

2007/05/10

erlang その8

続ets module

ets:foldlとets:foldr関数を使ってみる。
lists:foldsとlists:foldrと同様だそうだ。

<ets_tut2.erl>

-module(ets_tut2).
-export([test/0]).


fold(Option)->
P = ets:new(test1,Option),
ets:insert(P,{a}),
ets:insert(P,{b}),
ets:insert(P,{c}),
CL = ets:foldl(fun(X, Con)->[X|Con] end, [{d}], P),
io:format("foldl ~p ~p~n", [Option, CL]),
CR = ets:foldr(fun(X, Con)->[X|Con] end, [{d}], P),
io:format("foldr ~p ~p~n", [Option, CR]),
ets:delete(P).


test()->
fold([]),
fold([ordered_set]).


実行結果は次のようになった。
1> c(ets_tut2).
{ok,ets_tut2}
2> ets_tut2:test().
foldl [] [{c},{b},{a},{d}]
foldr [] [{c},{b},{a},{d}]
foldl [ordered_set] [{c},{b},{a},{d}]
foldr [ordered_set] [{a},{b},{c},{d}]
true

Optionが空、つまりsetの場合は、foldlとfoldrの結果は同じになった。
一方、ordered setの場合は、foldlとfoldrの結果は異なった。

ordered setの場合、foldlは最初の要素から順に関数を実行していくので、
まず初期値[{d}]の前方に{a}が付けられる。したがって、[{a},{d}]となる。
つぎの要素は[{b}]なので、[{b},{a},{d}]となり、最後の要素の処理が終わると、
[{c},{b},{a},{d}]となる。
foldrの場合はその逆に動作するので[{a},{b},{c},{d}]となる。


次に、ets:lookupとets:lookup_elementを使ってみる。
<ets_tut3.erl>
-module(ets_tut3).
-export([test/0]).


test()->
lookup([set]),
lookup([ordered_set]),
lookup([bag]),
lookup([duplicate_bag]).


lookup(Option)->
P = ets:new(test1, Option),
ets:insert(P, [{a,10},{a,20},{a,20},{b,1},{b,5},{b,2}]),
io:format("~p ~p~n", [Option, ets:lookup(P,a)]),
io:format("~p ~p~n", [Option, ets:lookup(P,b)]),
io:format("~p ~p~n", [Option, ets:lookup_element(P,a,2)]),
io:format("~p ~p~n", [Option, ets:lookup_element(P,b,2)]),
ets:delete(P).


実行結果は次のようになった。
1> c(ets_tut3).
{ok,ets_tut3}
2> ets_tut3:test().
[set] [{a,20}]
[set] [{b,2}]
[set] 20
[set] 2
[ordered_set] [{a,20}]
[ordered_set] [{b,2}]
[ordered_set] 20
[ordered_set] 2
[bag] [{a,10},{a,20}]
[bag] [{b,1},{b,5},{b,2}]
[bag] [10,20]
[bag] [1,5,2]
[duplicate_bag] [{a,10},{a,20},{a,20}]
[duplicate_bag] [{b,1},{b,5},{b,2}]
[duplicate_bag] [10,20,20]
[duplicate_bag] [1,5,2]
true

lookupは第2引数で指定したキーに一致する要素一覧を取得する。
setとordered_setの結果は同じ。
bagは同じキーの重複は許されるが、内容が全て同じ要素の重複は許されない。
duplicate_bagはどのようなケースでも重複が許される。
そのため、キーaに対するbagとduplicate_bagの結果が異なっている。

lookup_elementの第3引数にはtupleの何番目の要素を取得するかを指定する。
ここでは2と指定したので、tupleの2番目の要素である数字のリストが得られる。

2007/05/09

erlang その7

ets:new とその関連関数を使ってみる。
これらの関数はテーブルを作成して、そこに色々な要素を記録しておくために使われるようだ。
C++のstd::mapの高機能版のようなものか?

まず、テーブルを作成する。
第1引数はテーブルの名前で、第2引数はオプションを指定する。[]でデフォルトが利用される。
Pにはテーブル識別子(マニュアルではtid()と記載されている)が代入される。
1> P=ets:new(table1,[]).
16

次にこのテーブルの情報を見てみる。
2> ets:info(P).
[{memory,279},
{owner,<0.30.0>},
{name,table1},
{size,0},
{node,nonode@nohost},
{named_table,false},
{type,set},
{keypos,1},
{protection,protected}]

マニュアルによるとmemory は 「The number of words allocated to the table.」
とのことなので、単位をbytesであるとはいえそうにない。
sizeはテーブルに記録されているオブジェクトの数で、今は空なので0になっている。

テーブルに要素を追加してみる。
3> ets:insert(P, {aaa}).
true

テーブルの情報をみると、
4> ets:info(P).
[{memory,289},
{owner,<0.30.0>},
{name,table1},
{size,1},
{node,nonode@nohost},
{named_table,false},
{type,set},
{keypos,1},
{protection,protected}]

となっており、要素数が1増えている。
さらに追加してみると、
5> ets:insert(P, {bbb}).
true
6> ets:info(P).
[{memory,299},
{owner,<0.30.0>},
{name,table1},
{size,2},
{node,nonode@nohost},
{named_table,false},
{type,set},
{keypos,1},
{protection,protected}]

要素数が2になった。また、memoryが10ずつ増えている。
もう少し短いatomを追加してみる。
7> ets:insert(P, {c}).
true
8> ets:info(P).
[{memory,309},
{owner,<0.30.0>},
{name,table1},
{size,3},
{node,nonode@nohost},
{named_table,false},
{type,set},
{keypos,1},
{protection,protected}]

要素数が3になり、memoryは前と同様に10増える。

要素を順番に見ていくには、ets:first/1とets:second/2を使う。
まずets:first/1を使って、
9> ets:first(P).
c

最初の要素はcのようだ。次にets:next/2を使って、
cの要素の次に記録されている要素を順次取得する。
10> ets:next(P,c).
aaa
11> ets:next(P,aaa).
bbb
12> ets:next(P,bbb).
'$end_of_table'

テーブルの最後までくると、'$end_of_table'が返される。
これで終端かどうかが判断できる。

ところで、このテーブルの機能は便利なのだが
テーブルに記録した値は変更できてしまうことになる。
使い方によってはC言語っぽい書き方ができてしまいそうだ。

また、ets.erlによると、これらetsモジュールの関数の一部、
例えばnewやfirst, nextの実装はC言語でされているとのことだ。

2007/05/08

erlang その6

ファイル名に.を含めてみる。
<ets.tut1.erl>

-module(ets.tut1).
-export([test/0]).
test()->io:format("~p~n", ["test"]).

これをコンパイルしてみると、
1> c(ets.tut1).
** Module name ''ets.tut1'' does not match file name ''ets.tut1'' **
{error,badfile}

となる。また試しに ' でくくってみた。
2> c('ets.tut1').
** 2: syntax error before: c **

やはりエラー。
どうやらファイル名を . を含めると正常に処理できないようだ。
リファレンスマニュアルによると
<引用>
The name Module, an atom, should be the same as the file name minus the extension erl.
</引用>
である。また、atomには . を含んでもよい。
このことから、ファイル名の途中に . を含めることができそうにみえるが、できないようだ。
マニュアルのどこかに別途この点について記載がされているのかもしれない…

2007/05/06

erlang その5

●正規表現ライブラリ regexp を使ってみる。

一致した位置を取得する関数 match を使ってみる。
最初の引数が処理対象の文字列で、第2引数が正規表現。
1> regexp:match("a,bc,def,123", ",").
{match,2,1}
結果の2番目が一致した位置で、この場合は最初の,が一致している位置なので、2になる。
0 originではなく、1 originである。
戻り値の最後の値は一致した文字数になので、1になる。

2> regexp:match("a,bc,def,123", ",d").
{match,5,2}
この例では2文字一致しているので戻り値の3番目の値が2になっている。

3> regexp:match("a,bc,def,123", ",d.f").
{match,5,4}
ピリオド.は任意の1文字に一致するので、,defが一致している。

4> regexp:match("a,bc,def,123", ",d.*2").
{match,5,7}
*は0個以上の文字に一致するので、.*で任意の0個以上の文字への一致を調べることになる。
なので、「,def,12」に一致することになり、一致した文字の長さは7文字になる。

マニュアルによるとmatchよりもfirst_matchを使用する方が速いとのこと。
使いかたは同じで、
5> regexp:first_match("a,bc,def,123", ",d.*2").
{match,5,7}

一致する部分を全てみつけたい場合は matches を使う。
6> regexp:matches("a,bc,def,123", ",").
{match,[{2,1},{5,1},{9,1}]}
コンマ,の場所を見付けているので、2文字目、5文字目, 9文字目が見つかる。

今度は、一致した場所の文字を置換する。置換には sub を使う。
この関数では最初に見つけた位置の文字を置き換えるだけ。
7> regexp:sub("a,bc,def,123", ",", " ").
{ok,"a bc,def,123",1}
返される結果の2番目は、置換処理後の文字列となっており、
最初のコンマがスペースに置き換えられている。

一致した場所全てを置き換えたい場合は gsub を使う。
8> regexp:gsub("a,bc,def,123", ",", " ").
{ok,"a bc def 123",3}
結果の3番目の値は置き換えた"箇所"の数で、この例ではコンマが3箇所あるので3になる。

一致した場所で文字列を分割する。これには split を使う。
9> regexp:split("a,bc,def,123", ",").
{ok,["a","bc","def","123"]}
コンマで分割された文字列のリストとして結果が返される。

今回はここまで。

2007/05/03

erlang その4

●ファイル
ファイルの入出力の方法について調べてみた。
まずは、ファイルからの読み込み。
<tut11.erl>

-module(tut11).
-export([read/1]).

read(FileName)->
Handle = file:open(FileName, read),
if element(1,Handle) /= ok -> element(1, Handle);
true -> show_content(element(2,Handle)),
file:close(element(2, Handle))
end.

show_content(Handle)->
Result = io:get_line(Handle, prompt),
if Result == eof -> ok;
true -> io:format("~p~n",[Result]),
show_content(Handle)
end.

さらにテスト用のファイルを作成する。
<test1.txt>
abc
def
123

コンパイルして、
6> c(tut11).
{ok,tut11}

実行すると、
7> tut11:read("test1.txt").
"abc\n"
"def\n"
"123\n"
ok

のような結果が得られる。
io:get_lineでは改行コードは除去されないようだ。

次にファイルへの書き出しを試してみる。
ついでにio:formatの~pと~wと~sの違いを見てみる。
<tut12.erl>
-module(tut12).
-export([write/2]).

write(FileName, Str)->
Handle = file:open(FileName, write),
if element(1,Handle) /= ok -> element(1, Handle);
true -> write_content(element(2,Handle), Str),
file:close(element(2, Handle))
end.

write_content(_, [])->ok;
write_content(Handle, [Head|Rest])->
io:format(Handle, "~p,~w,~s~n", [[Head],[Head],[Head]]),
write_content(Handle, Rest).

コンパイルして、
36> c(tut12).
{ok,tut12}

実行してみる。
41> tut12:write("test2.txt", ["abc"]).
出力されたファイルの内容は、
["abc"],[[97,98,99]],abc

つまり、
~p : 入力された内容をそのまま出力。
~w : 各文字を値として解釈
~s : 文字列として解釈
ということになるようだ。(詳しくはerlangのreference manualを参照のこと)

今度は、日本語に挑戦。
ただ、erlang shellは日本語を受け付けてくれないので、
UTF-8の文字コードを直接入力してみる。

42> tut12:write("test2.txt", [227,129,130]).
出力されたファイルの内容は、
"�",[227],
[129],[129],�
[130],[130],�

ん?各値ごとに出力しようとしているようだ。

["abc"]のようにするには、
46> tut12:write("test2.txt", [[227,129,130]]).
とすればよい。
この出力結果は、
[[227,129,130]],[[227,129,130]],あ

のようになる。~sの出力が日本語になっている。
むろん、UTF-8で日本語が表示できるUNIX shell等で表示させている。

erlang その3

●文字列に関して
Atomは文字で、小文字から始まらないorアルファベットか数字以外の文字で
構成されるときはシングルクォート'で囲まないといけない。

Stringはダブルクォート"で囲まれた文字。
Erlangのデータ型ではなく、Listとして表現される。

●Shellに関して
Shellで定義した変数を消去するには、f()を使うとよい。
1> X=1.
1
2> X=2.

=ERROR REPORT==== 2-May-2007::22:19:18 ===
Error in process <0.30.0> with exit value: {{badmatch,2},[{erl_eval,expr,3}]}

** exited: {{badmatch,2},[{erl_eval,expr,3}]} **
3> f().
ok
4> X=2.
2

さらに特定の変数の定義を除去することもできる。
5> Y=3.
3
6> X=3.

=ERROR REPORT==== 2-May-2007::22:20:08 ===
Error in process <0.33.0> with exit value: {{badmatch,3},[{erl_eval,expr,3}]}

** exited: {{badmatch,3},[{erl_eval,expr,3}]} **
7> Y=2.

=ERROR REPORT==== 2-May-2007::22:20:10 ===
Error in process <0.38.0> with exit value: {{badmatch,2},[{erl_eval,expr,3}]}

** exited: {{badmatch,2},[{erl_eval,expr,3}]} **

この時点で、X=3, Y=2となっている。
8> f(Y).
ok

これでYの定義のみが消去された。なので、
9> X=3.

=ERROR REPORT==== 2-May-2007::22:20:18 ===
Error in process <0.40.0> with exit value: {{badmatch,3},[{erl_eval,expr,3}]}

** exited: {{badmatch,3},[{erl_eval,expr,3}]} **

のように、Xは定義済みなので再定義できないが、Yについては先ほど消去しているので
10> Y=2.
2
のように再定義できる。

●erlangプログラムのコンパイル
いろいろ探してみたが、ネイティブコードを出力するコンパイラを見つけられない…

とりあえず、UNIXのshellから実行できるようにするには、
(1)コマンドラインから.erlファイルを実行
(2).erlプログラムの最後にhalt().を書いて、shellを止める
の2つを行うしかなさそうだ。

あんましよさげではないが、例えば
<tut10.erl>
-module(tut10).
-export([main/1]).
main(X)->io:format("~p~n",[X]),
     halt().

のようなファイルを作成し、
UNIX> erl -compile tut10.erl

としてコンパイルして、
UNIX> erl -noinput -run tut10 main abc
["abc"]

のようにして実行する。ちなみに日本語を入れると、
UNIX> erl -noinput -run tut10 main あ
[[227,129,130]]

となり、日本語の出力ができない。
データの値からしてUTF-8でエンコードされているようだ。
なので、ファイルにバイナリで出力できれば読めそう。

erlang shell や UNIX shell に日本語を出力する方法は見つけられず…

2007/05/01

erlang その2

今度は、標準モジュールの説明。
マニュアルはコマンドラインから
# erl -man io
で見ることができる。この場合は、ioモジュールのマニュアルが表示される。
これはerlangのシェルからではなく、csh等の通常のシェルから実行する。

# io:format("test~n").
test
ok
# io:format("test~n", []).
test
ok

引数なしでも空リスト引数でも表示できる。

# io:format("test ~w.~n", [AAA]).
** 1: variable 'AAA' is unbound **
大文字だと文法違反のようだ。

# io:format("test ~w.~n", [aaa]).
test aaa.
ok
小文字ならOK。

# io:format("test ~w.~n", ["AAA"]).
test [65,65,65].
ok
""で囲むと文法違反にはならないが、文字列ではなく数字のリストに変換される。

6> io:format("test ~w.~n", ['AAA']).
test 'AAA'.
ok
''で囲むと望みどおりのAAAが表示される。

# io:format("test 1:~w 2:~w ~~.~n", ['AAA','BBB']).
test 1:'AAA' 2:'BBB' ~.
ok
2つ以上表示させたい場合は、リストの要素を増やせば良い。
フォーマット部分の文字列には~wを2個書く。このへんはC++のboost:formatのようだ。
~を表示させたいときは~~と書けば良い。

次に最小値を求める関数を作成する。
ここでは「guard」というのを使用する。

<tut6.erl>
-module(tut6).
-export([list_min/1]).
list_min([Head|Rest])->list_min(Rest, Head).
list_min([], Result)->Result;
list_min([Head|Rest], Result) when Head < Result ->list_min(Rest, Head);
list_min([Head|Rest], Result)->list_min(Rest, Result).

実行すると、
# c(tut6).
./tut6.erl:6: Warning: variable 'Head' is unused
{ok,tut6}
# tut6:list_min([7,2,5,7,9,1,3]).
1
のようになり、最小値が得られる。「when」というのが関数実行の条件で、
trueの場合に関数の中身が実行される。そうでない場合は、関数の次の定義が実行される。
このように条件をテストすることを「guard」と呼ぶようだ。

guardで使える条件文は <, >, == <=, >=, /=がある。
/=はnot equalであり、C++とは違うので注意。

リストにはもう少し機能がある。| operatorにはリストの先頭に要素を追加する機能がある。
まず、リストを作成する。
# L = ['AAA','BBB'].
['AAA','BBB']

| operatorでリストの先頭に要素を追加する。
# L3 = ['CCC'|L].
['CCC','AAA','BBB']

逆向きに書くと、
# L2 = [L|'CCC'].
[['AAA','BBB']|'CCC']
となり、'CCC'のみ持つリストの先頭に['AAA','BBB']というリストが
追加されることになる。

これを使って、リストの順序を逆にする関数を作ってみる。
<tut8.erl>
-module(tut8).
-export([reverse/1]).
reverse(List)->reverse(List, []).
reverse([Head|Rest], ReversedList)->reverse(Rest, [Head|ReversedList]);
reverse([], ReversedList)->ReversedList.

4行目でHeadから順にReversedListの先頭に追加しているところがミソ。
# c(tut8).   
{ok,tut8}
# tut8:reverse([1,2,3,4,5]).
[5,4,3,2,1]
逆順になった。

関数に連続した処理をさせたい場合は、「,」で区切ればよく、
<tut7a.erl>
-module(tut7a).
-export([format/1]).
format(Str)->
  io:format("test : ~w~n", [Str]),
  io:format("test2 : ~w~n", [Str]).

のように書ける。これを実行すると、
# c(tut7a).    
{ok,tut7a}
# tut7a:format(aa).
test : aa
test2 : aa
ok

となり、文字列の出力を2回行うようになる。
今度は与えられた値のリストから最小値と最大値をとってみる。
<tut7b.erl>
-module(tut7b).
-export([minmax/1]).

minmax([Head|Rest])->minmax(Rest, Head, Head).
minmax([Head|Rest], Min, Max)->
  if Head < Min -> NewMin = Head;
    true -> NewMin = Min
  end,
  if Head > Max -> NewMax = Head;
    true -> NewMax = Max
  end,
  minmax(Rest, NewMin, NewMax);
minmax([], Min, Max) -> {Min, Max}.

コンパイルして実行してみる。
# c(tut7b).
{ok,tut7b}
# tut7b:minmax([1,2,3,4,5,6,7]).
{1,7}
# tut7b:minmax([5,3,8,0,2,4,5]).
{0,8}

たしかに最小値と最大値がとれている。
条件文ifは上記のように書けばよく、条件の間は;で区切る。
endの直前の条件文には;はいらない。
elseがないので、代わりに一番最後にtrue->とすることで対応する。

もう少しifについて調べてみる。
<tut9.erl>
-module(tut9).
-export([test/2]).

test(X,Y)->
  if X==1 -> 'X == 1';
    Y==2 -> 'Y == 2';
    X==2, Y==5 -> 'X==2, Y==5';
    X==3;
    Y==4 -> 'X==3 or Y==4';
    (X==5) and (Y==5) -> 'X==5 and Y==5'
  end.

実行すると、
# c(tut9).
{ok,tut9}
# tut9:test(1,2).
'X == 1'
Xが1なので、一番最初の条件に一致する。

# tut9:test(0,2).
'Y == 2'
Xが1でなく、Yが2なので、2番目の条件に一致する。

# tut9:test(2,5).
'X==2, Y==5'
今度は3番目の条件に一致する。

# tut9:test(3,5).
'X==3 or Y==4'
これは4番目の条件に一致する。
C++でいうswitch-cast文と似ていて、;のみで->がない場合は、
->が見つかったところから実行するようだ。

# tut9:test(5,5).
'X==5 and Y==5'
最後は両方共が5の場合の条件である。

# tut9:test(6,5).

=ERROR REPORT==== 1-May-2007::17:01:33 ===
Error in process <0.44.0> with exit value: {if_clause,[{tut9,test,2},{shell,exprs,6},{shell,eval_loop,3}]}

** exited: {if_clause,[{tut9,test,2},{shell,exprs,6},{shell,eval_loop,3}]} **
条件にマッチしないとこんな風にエラーになる。

ちなみに10行目を
 (X==5) and (Y==5)
と書かず、
 X==5 and Y==5
と書くとコンパイルエラーになる。

最後に高階関数(higher order functions)について試してみる。
C++でいう関数ポインタみたいなもの。
シェルから使うと、次のようになる。

18> Fn = fun (X)->X*3 end.
#Fun<erl_eval.6.56006484>
19> Fn(5).
15

引数の値を3倍する関数Fnを定義して、その引数に5を入れると15が出力される。
高階関数の定義はfunとendで囲むようだ。

標準モジュールのlistsを使うと、次のようなことができる。
20> lists:map(Fn, [1,2,3]).
[3,6,9]

リスト[1,2,3]の各要素に対してFnを適用し、その結果をリストに入れる操作が行われている。

他にも、
25> Fp = fun (X)->io:format("elm : ~w~n",[X]) end.
#Fun<erl_eval.6.56006484>
26> lists:map(Fp, [1,2,3]).
elm : 1
elm : 2
elm : 3
[ok,ok,ok]
27> lists:foreach(Fp, [1,2,3]).
elm : 1
elm : 2
elm : 3
ok
といったことができる。

ソートも次のようにできる。
30> lists:sort([2,3,1]).
[1,2,3]
31> lists:sort(fun(X,Y)->X<Y end,[2,3,1]).
[1,2,3]
32> lists:sort(fun(X,Y)->X>Y end,[2,3,1]).
[3,2,1]

名前とペアになっている要素からなるリストに対してもソートできる。
33> lists:sort(fun({_,X},{_,Y})->X<Y end,[{'A',2},{'B',3},{'C',1}]).
[{'C',1},{'A',2},{'B',3}]

ここで、「 _ 」はanonymous variableと呼ばれ、使わない値に使用するようだ。
今の例では、文字は比較に使わないので「 _ 」を使って表現を簡略化した。

今回はここまで。

2007/04/30

erlang その1

erlangという関数型言語のプログラミング言語を使ってみる。
getting started を見ながらやってみることにする。
http://www.erlang.org/

起動するにはコマンドラインから
# erl
と入力する。

何か計算をさせてみる。
# 1 + 2.
3
と表示される。最後のピリオドはC++でいう;に相当するようだ。

括弧で優先順位をきめられる。
# (1+2)*5.
15

erlシェルを終了したいときはCtrl+Cを押すと
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
と表示されるので、aを押すと終了する。

今度はファイルにソースを書いて、コンパイルしてから使ってみる。
[tut.erl]ファイルの中身に次のように書く。

-module(tut).
-export([double/1]).
double(X) -> 2*X.

そして、
# c(tut).
{ok,tut}
でコンパイル完了。
使うには、
# tut:double(50).
100
とすると、結果に2倍された値が表示される。
ところで、

-module(tut).
-export([double/1]).
double(x) -> 2*x.

つまり、Xをxに書き換えるとコンパイルが通らない。
チュートリアルの後の方に書いてあるが、
変数の先頭の文字が大文字か小文字かによって意味が変わるようだ。

今度は再帰。ループが使えないのでその代わりに使うようだ。
ためしに、1からXまでの値を足すプログラムを書いてみる。

-module(tut1).
-export([sum/1]).
sum(1)->1;
sum(X)->X+sum(X-1).

重要なのは、3行目のsumの定義の最後を;にすること。
もし.を使うとsumの定義が終了して、4行目で再定義されてしまうことになり、
コンパイルエラーになる。

さて、実行してみると、
# tut1:sum(10).
55
で、あってる。

今度は、このファイルに関数powを追加してみる。

-module(tut1).
-export([sum/1, pow/2]).
sum(1)->1;
sum(X)->X+sum(X-1).
pow(X,1)->X;
pow(X,Y)->X*pow(X,Y-1).

コンパイルして実行してみる。
# tut1:pow(2,8).
256

おそらく意外とC++とかでは面倒なことになりそうな2^1024を計算してみる。
# tut1:pow(2,1024).
17976931348623159077293051907890247336179769789423065727343008115773267580
55009631327084773224075360211201138798713933576587897688144166224928474306
39474124377767893424865485276302219601246094119453082952085005768838150682
34246288147391311054082723716335051068458629823994724593847971630483535632
9624224137216

合ってるのかどうかわからんが、たぶん正しいのだろう。
多倍長整数があるのはこういうときは便利だ。

今度はAtomsとかいうデータ型を使ってみる。
tut2.erlファイルを作って、次のような内容を記録する。
単位系を光年←→パーセクへ変換する関数である。

-module(tut2).
-export([convert/2]).
convert(L, parsec)->L/3.26;
convert(P, lightyear)->P*3.26.

# c(tut2).
{ok,tut2}
# tut2:convert(3, parsec).
0.920245
# tut2:convert(3, lightyear).
9.78000

第2引数の値によって、関数の呼ばれる部分が変わるということのようだ。
で、その第2引数が数字ではなくて、atomだということだろう。

次はTuplesだ。
値をひとまとめにして扱おうということだ。C++でいう構造体に似ているかな。
ここでは数字を単位と一つにまとめて処理してみる。
<tut3.erl>
-module(tut3).
-export([convert_length/1]).
convert_length({L, lightyear})->{L/3.26,parsec};
convert_length({P, parsec})->{P*3.26,lightyear}.

で、実行。
# c(tut3).
{ok,tut3}
# tut3:convert_length({3,parsec}).
{9.78000,lightyear}

計算できてる。無論、tupleの要素の位置を逆にしても同じことができる。
<tut3b.erl>
-module(tut3b).
-export([convert_length/1]).
convert_length({lightyear, L})->{parsec, L/3.26};
convert_length({parsec, P})->{lightyear, P*3.26}.

実行すると、
# c(tut3b).
{ok,tut3b}
# tut3b:convert_length({parsec,3}).
{lightyear,9.78000}
となって、逆にしてもOK。

次はListsだ。listは[]で囲む。
tupleと違って、サイズを変えられる。C++でいうとstd::listかな。
例えば、
# [First | TheRest] = [1,2,3,4,5,6,7].
[1,2,3,4,5,6,7]
# First.
1
# TheRest.
[2,3,4,5,6,7]
な風になる。|はリストの最初の要素と後の要素をわける。
コンマを使うと、要素ごとに分けられる。
# [First, Second | TheRest] = [1,2,3,4,5,6,7].
[1,2,3,4,5,6,7]
# First.
1
# Second.
2
# TheRest.
[3,4,5,6,7]

ちなみ、この2つの例を連続していれると、文句を言われる。
つまり、最初に定義したFirstを次の定義のFirstで上書きしていると。
定義済みの変数の消し方がわからんので、ここではerlを再起動して例を試した。

次に、リストの長さを求める関数を定義する。
<tut4.erl>
-module(tut4).
-export([list_length/1]).
list_length([])->0;
list_length([First|Rest])->1+list_length(Rest).

使ってみる。
# c(tut4).
./tut4.erl:4: Warning: variable 'First' is unused
{ok,tut4}
# tut4:list_length([1,2,3,4,5]).
5
警告がでたが、問題なく動作するようだ。
要素にatomを使ってもOK.
# tut4:list_length([a,b,c,d,e,f]).
6

ついでに文字列はどうなるかみてみる。
# tut4:list_length(["a","b"]).
2
""が何を意味するのか読んでいるチュートリアルの現時点では不明だが、
なにかの値として見てはくれているようだ。

# ["a","b"].
["a","b"]
ただ、リストの内容が表示されるだけ。

# [97,98].
"ab"
なんと、文字コードとして解釈してくれるようだ。
でも["a","b"]のときは気をきかせて"ab"と表示してくれるわけではないようだ。

============================
今回はこの辺で終了。

状態!?

<引用>
「新・闘わないプログラマ No.487」
http://www.amy.hi-ho.ne.jp/~lepton/program/p4/prog487.html
「状態」というのを理解して、それに応じた操作ができない人もいるので、「状態」を出来る限り作らないようなユーザーインターフェースが必要なのでは
</引用>

なるほど。
同じキーにたくさん機能を割り当ててると難しいわけか。
んで、避けようとすると、HDDレコーダのリモコンのように
余計わけ分からん状態になるってことだ。

多機能にすると、ボタンの数を増やすか「状態」を使って
1つのキーにいろんなことをさせんといかんわけで。

んー、要はシンプルに作るべきだってことだ。

Debian 4.0で遊ぶ その1

Debian 4.0 r0をインストールしてみた。
以下、そのログ。あんまり参考にはならないかも。

とりあえず、
http://www.debian.org/CD/netinst/
に書いてある方法で進める。

(1)ダウンロードするのは
debian-40r0-i386-netinst.iso
で、これをCDに焼く。

(2)CDからブートして、画面が表示されたらEnterを押す。
しばらく待つと、インストーラが立ち上がる。
今回使ったCDドライブはUSB接続のもの。

(3)まず言語を選ぶ。

(4)さらにキーボードの種類を選ぶ
すると、CDの検査が始まり、続いて追加コンポーネントのロードが始まる。

(5)ネットワークインターフェイスが複数あるため、
選択画面が出てくる。
Marvell Technology Group Ltd. 88E8053 PCI-E Gigabit Etherne
と表示されているものを選択。
DHCPでネットワークを検索し始める。
が、LANをつないでいない!ので見つからず。
そのまま「続ける」ボタンを押す。

(6)どうするか選択肢がでてくる。
・ネットワークの自動設定を再試行
・DHCPホスト名付きでネットワークの自動設定を再試行
・ネットワークを手動で設定
・今ネットワークを設定しない
3番目を選ぶ。

(7)IPアドレス、サブネットマスク、ゲートウェイ、ネームサーバーアドレスを設定。
若干、待つと、次の設定画面が現れる。

(8)システムのホスト名を入れる画面がでてくるので、
好きな名前をいれる。

(9)ドメイン名を入れる画面がでてくるので、
適当なのを入れる。

(10)ディスクのパーティショニングが画面が出てくる。ここでは
「ディスク全体を使い、暗号化LVMをセットアップする」を選択した。

(11)ディスクのパーティショニングするディスクを選択する。

(12)パーティショニング機構の選択画面になる。
ここでは、「すべてのファイルを1つのパーティションに」を選択

(13)ディスクへの変更をHDDに書き込むかの最終確認画面が出てくる。
「はい」を選択。

(14)HDDへアクセスするためのパスワードを設定する。
たぶん暗号化LVMを選んだためと思われる。

(15)ファイルシステムを書き込む前の確認画面が表示される。
/bootパーティションのみ通常のext3で、
残りはなぜかhda5_cryptに割り当てられている。
なぜにhda5なのかは分からない。
とにかく、「パーティショニングの終了とディスクへの変更の書き込み」を選択

(16)確認画面がでるので「はい」を選択

(17)Rootパスワードを要求される。

(18)ユーザー名の入力する

(19)新しいアカウントのユーザー名を入力する

(20)ユーザーのパスワードを設定する

(21)「ベースシステムをインストールしています」と表示され、
インストールが始まる。

(22)パッケージマネージャの設定で、
ネットワークミラーを使うかどうかを聞かれる。
「はい」を選択

(23)アーカイブミラーを選択

(24)ftp.jp.debian.orgを選択

(25)HTTPプロキシを設定する。とりあえず空でいく。
ミラーを検査していますと表示される。

(26)正しくないアーカイブミラーですと表示され、
画面が赤くなる。
どうやらネットワークに接続できていないようだ。

(27)設定をもどって、DHCPを使うように変更し、リトライ。

(28)debianパッケージ利用調査に参加しますか?
には「いいえ」。どっちでもよいと思うけど。

(30)ソフトウェアの選択では
デスクトップ環境, ウェブサーバ, 標準システムにチェック

(31)ネットワークからいろいろとダウンロードが始まる。項目数は700程度。
待つ
待つ
待つ








まる1日かかった… 。狭帯域なもので(w

(32)インストールが始まると、途中で使用する画面の解像度が聞かれる。

(33)途中でX関連の設定で失敗した。
ディスプレイの接続が切れていたせいかもしれない。

(34)やり直しを前回と同じ、
 デスクトップ環境, ウェブサーバ, 標準システムにチェック
実行すると、またダウンロードが始まった。
どうやら、前回ダウンロードできてなかった部分を落としているようた。
ファイルを取得しています xx/78 となっていて、78個落とす必要があるようだ。
待つ



こんどは1〜2時間待ち…

(35)ハードディスクへGRUBをインストール

(36)インストールの完了画面が表示される。
ので、CD-ROMをドライブから抜いて、「続ける」ボタンを押す。
すると、再起動が始まる。

ようやくインストール終了。
これからいじっていく予定。

2007/04/28

HDD 500GB

またHDD(HD-HC500U2)を買ってきた。25800円だった。

前回と同じく、箱の背面に緑色の丸いシールが、側面には赤い丸いシール貼ってある。
しかし今回はさらに、箱の上部に赤い丸いシールと四角い朱色(オレンジ色?)のシールが貼ってある。

以前の調査と同様、HDDのプロパティを見ると、
 WDC WD50 00AAKS-00TMA0
と書いてある。
たぶん、これ↓
http://www.wdc.com/jp/products/products.asp?driveid=301&language=en

ちなみに初期のFAT32フォーマットでは容量が499,983,122,432バイト。
NTFSでフォーマットしなおしたところ、500,105,216,000バイトとなり、
ちょっと増えた。

2007/04/25

ボッコロの日

今日はボッコロの日だ。イタリアはヴェネチアの習慣だそうで。

2007/04/24

ニュース

エリツィン大統領が死去とのこと。
いつ大統領をやめたのか忘れたが、時が進んでるのを感じるな。

2007/03/04

オフショア vs Agile

オフショア vs Agile について
http://d.hatena.ne.jp/masayang/20070302/1172860846

とりあえず、リンクだけメモ
オフショア:従来型より不具合増
Agile:従来型より不具合減

だそうだ。

2007/02/07

( 続々 )500GB HDD

昨日、またHDD(HD-HC500U2)を買ってきた。25800円だった。

箱の背面に緑色の丸いシールが、側面には赤い丸いシール貼ってある。
以前の調査と同様、HDDのプロパティを見ると、
 Hitach HDT725050VLA360
と書いてある。

日立製のDeskstar T7K500シリーズのようだ。
http://www.hitachigst.com/portal/site/en/menuitem.f053c8a6f66a6a14e85c1a70eac4f0a0/
http://www.hitachigst.com/tech/techlib.nsf/products/Deskstar_T7K500

フォーマット中の現時点では、筐体が熱くなりすぎているということはない。
ファンから出てくる排気は、ほんのり暖かい程度だ。

それにしても、毎回毎回買うたびにメーカーが違うので、
くじ引きみたい…。

2007/01/14

博士が100にんいるむら

博士(はくし)が100にんいるむら
http://www.geocities.jp/dondokodon41412002/index.html

なかなか現実的なはなしになってますな。

読んだほうが雰囲気がわかりますが、
博士取得者の進路を数字だけにするとこんなかんじ。

16% 医者
14% 大学(助手等)
20% ポスドク
8% 会社員
11% 公務員
7% 他分野へ
16% 無職
8% 行方不明or死亡

理学博士と工学博士で同じような分類をして比較したら
きっと差が出るだろうな。特に一番下のほうが…

ところで、このデータってどこからとってきたんだろう?

2007/01/07

攻殻機動隊 SSS

今頃、攻殻機動隊Solid State Societyを見てみた。
なかなか面白かったなぁ。何回か観れそうだ。
ただ、108分じゃちょっと短いようで、展開が早過ぎる感があったな。

以下、とりとめのない感想。

【タチコマ】
前作のSAC2でタチコマが衛星ごと失われたので、
今回の9課にはウチコマが配備されていた。
フチコマかと思いきやウチコマだった。形は似てるのにね。
天然オイルを使っても個性がでていないようだけど。

片や素子の支援AIのタチコマには固有名が振られてて、
マックスとかコナンとかムサシとかロキとかつけられている。
誰がどの色なのかはわからんかった。
名前は漫画の攻殻機動隊2から取ってきてるみたいだ。

一応、後半では前作同様の体を使ってたけど。
こっちは全部青色で統一されてる。

【バトー】
今回のバトー君はひたすらサポート役。

【トグサ】
隊長さんになったトグサ君は携帯電話経由で電脳ハックされてた。
こんな世界になったらおちおち電話もとれませんな。

・自殺しようとしたときに使った銃ってマテバかな?
・背景の案内板の電脳小児科ってなに?
・トグサ自殺阻止後のバトーと素子との有線のときのシーンに出てきた
 TOGUSA MEGA GAIZ NEURO COMPUTERってのは
 ネットを漂流していたデータから組み上げられたものかな?
・トグサの娘さん、名前がなかった。

【素子】
スタッフロールで草薙素子(クロマ)ってなってたが、
えーっと、どれがクロマだったんだろう。
まぁどれでも義体が違うだけで本体は同じだからどれでもいいが。

今回の素子の義体は全て遠隔操作みたいにみえるし、
本体はどこにいるのやら。
本拠っぽい部屋が描かれているシーンはあったが、
たしかそこには3人というか3体いたな。

物語の最後のほうでコシキが自殺するが、
その直後に草薙がコシキに接続した際に
コシキがようやく草薙と有線できたとかいっている。
目的は草薙との有線だったようなので、
有線後から意味消失するまでの会話をしている間に融合をしたのかな?

というのも、漫画の攻殻機動隊2の荒巻素子(素子11)がSSSの草薙素子で、
アンタレスやスピカのような他の同位体(傀儡廻し)がコシキを操っていたように思えるからだが。
あれ、逆か!?

【監視カメラ】
作品中のところどころのシーンに監視カメラから見た視点が挟まっていたが、
傀儡廻しか草薙素子かどっちが見ている視点だったのだろう。
どっちが見ていたとしても特に解釈に困ることはなさそうだし。
びみょーだ。