HSP2.xで実験用プログラムを作るときのあれこれ

HSP3 がリリースされたので以下凍結。

支援用品

サクラエディタ用

サクラエディタのYahoo!グループ ブリーフケースに サクラエディタ用 Hot Soup Processor 2.55 設定セット( hsp_20020807_20.lzh )があります。 強調キーワード,キーワードヘルプ辞書ファイル,アウトライン解析ルールファイルが含まれています。 しかしこれは2.55のときのセットなのでいささか古いです。 HSP2.61用は強調キーワードだけなら拙作のものがダウンロードできます

EmEditor用

強調文字列 構文ファイル hsp261.esy

「設定のプロパティ」の「強調」タブでインポートしてください。 「表示」タブで色設定をするのを忘れないように。

変数のネーミング,名前空間

HSPは変数が自動的に作られる。これは初心者にとってはありがたい簡便性を 提供することになるのだろうが,心理学実験くらいの, ある程度以上の規模のプログラムを作ろうとすると,厄介な問題になる。 下は n の階乗を計算しようとしたプログラム。

n = 5
result = 1
repeat n, 1
	result = resalt * cnt
loop
mes result

実行すると,n をいくらにしようが,0 が表示されるだろう。 何が間違っているのか?答えは単純なスペルミスである。 resultresalt と誤って綴っている箇所がある。 HSPではこれがエラーにならない。 resaltresult とは別の新たな変数とみなされ, 中身は自動的に 0 にセットされる。結果として, 何回ループをまわしても常に result に 0 を代入することになり, n がどんな数であろうが mes では 0 しか表示されない。

こんな例のようにミスが見た目に直結するような見つけやすいものであればよいが, 込み入ったルーチンのどこかでこんなことをやってしまっていたら見つけるのも一苦労だし, 最悪の場合,本番の実験を走らせて変なエラーが出たりデータがきちんと記録されていなかったり するまで気づかない,ということもある。 せっかく参加者に実験室まで来てもらったのに,とんでもない泣きを見ることになる。

VBなどと違って,HSPにはこれを回避するまともな方法は用意されていない。 つまり,回避するには最終的には「プログラマが変数名に気をつけろ」と言うしかない。 しかしこういうミスは上記の例のように,気をつけていても「いつの間にか」入ってしまうものであり, 注意を持続しろ,のような無茶な根性主義だけではどうにもならない。

また,プログラムが大きくなるに従って, どこでどんな名前の変数名を使ったのかを覚えておけなくなってくる。 これが問題になるのは言うまでもない。プログラムの別の箇所でいつのまにか 変数の値を書きかえてしまうかもしれない。 何かの拍子でプログラムが変な動きをするようになってしまって大変な目に合う。 プログラムが延々と終わらないとか。

よって,できる限りこのようなミスを少なくするためのプログラミングの癖,あるいはスタイルを 身に付けて,日ごろからそれを実践しておくのがせめてもの対策である。

ネーミング

対策のひとつは,変数のネーミング,すなわち,名前の付け方の工夫である。 推奨されるのは,プログラム中のその部分でしか付けないだろう名前を付けることだ。 プログラムの複数の部分(よくあるのは複数のファイル)で同じような変数名を (別々の目的で)使うことは,バグを生み出す原因になる。 そのルーチンが行う仕事に関係した,特異的な名前を付けるのがよい。 そうすれば,ほかの場所でその変数を誤って変更してしまう可能性はほぼなくなるし, 特定の変数名の登場範囲が狭まるのでデバッグもしやすくなる。 中にはファイル名などを接頭辞や接尾辞として変数名に付ける人もいる。

アルファベット1文字の名前の変数を使うことを禁止しはしない。 いつも長い変数名をタイプしていてはそれこそ効率が悪い。 しかし,1文字変数は一時的変数としてのみ用い,用いる範囲 (その変数を例えばループなどで使ってどうこうする範囲) もモニタの一画面で見える行数に限る,というポリシーを守ることを勧める。 この「一画面で見える範囲」という根拠の不明な上限は,Cなどの言語で 1つのサブルーチンの長さの目安としてまことしやかにささやかれているものである。 実際のところそうすればミスが減りそうには思えるので,守って悪くはないだろう。

変数名にはもちろんシステムで何かの命令の名前として用いられている単語は使えない。 しかし命令はごまんとあり,とても覚えきれるものではない。 衝突を避けるためには,指定の単語を強調表示できるエディタを使うのがよい。 例えばサクラエディタ強調キーワードを適切にセットして使うと,自分がシステム命令を 入力したときに色を変えて表示してくれる。 これでいちいちマニュアルを調べることなく,その変数名を使ってよいかどうかを確認できる。

実はHSPでは日本語を変数名に使うこともできる。 これを利用するのもひとつの改善策ではあろう。 少なくとも日本人が変数名のスペルミスをすることは減るはずだ。 ただ,これ(変数名への日本語使用)は昔バグがあった事項なので(すでに修正と発表されている), プログラムの正常動作への不安は心持ち増す気がしないでもない。

名前空間

高機能なプログラミング言語の中には名前空間を限定する機能を持っているものもある。 HSPにおいても,幾分これが有用である。

おおざっぱにこの機能を説明する。 識別子(名前)が一意の対象を指すためには,重複してはならない(名前がかぶってはいけない)のだが, この重複禁止の範囲を1つの空間とし,複数の空間を1つのプログラム内で利用できるようにする。 すなわち,名前を一意にしておかなければならない範囲は通常は(名前空間の機能がなければ) プログラム全体だが,それを局所化するのである。 例えば,名前空間 A と B があった場合, 名前空間 A の変数 x と名前空間 B の変数 x は同じ x という名前ながらも別の実体として定義される。

名前空間をローカルに限定することができれば, プログラマが変数の名前を気にしなければならない範囲はぐっと小さくなる。 これがバグの回避に有効なのは言うまでもない。

名前空間の切り分けと見なせる機能は,HSPでは #module ~ #global という記述を使って実現できる。 この間に挟まれた部分のソースはその外とは別の名前空間である。 すなわちこの中で作った変数 a はその外での変数 a とは別の変数である。 次の例では,(1)では "abc" と表示され,(2)では "123" と表示される。

#module "mymodule"

*label123
  a = "123"
  return

#global

  a = "abc"

  gosub *label123@mymodule

  mes a           ; (1)
  mes a@mymodule  ; (2)

#module#global の間はその中に明示的にジャンプしない限り実行されない。 そして,gosub でモジュールの中へジャンプするのだが,"123"を代入されるのは #module "mymodule" の中の a ,すなわち a@mymodule である。 @ はHSPにおいて名前空間(モジュール名)を明示指定するときに使用する。 変数名だけでなくラベルについても同様。

実はHSPにおけるこの #module ~ #global という命令は,その名前から示唆されるように, 名前空間よりももう少し高度なコンセプトに基づくものである。 それはプログラムのモジュール化である。 すなわち,プログラム全体を複数の細かなモジュール(部品)に分け, それぞれのモジュール内で1まとまりの機能(例えばcsvファイルの出力,など) を実現するようにコーディングし, それを組み合わせることで最終的な1つのプログラムを作ろうという, 一種のプログラミング・ストラテジーである。 これに従えば,各モジュール間はその結合部分(インターフェイス)以外はまったく互いに干渉せず, 内部完結しているのが最も望ましい。そうすれば, 個々のモジュールを別々に(異なる場所で異なる時間に異なる人が)開発することも容易になる。 そのために,モジュール内部の名前空間はモジュール外部と独立であるのがベストで, HSPの #moduel はこれを実現するための機能である。 その証拠に,モジュールのインターフェイス定義と見なせる命令 #deffunc#module ~ #global 内であってもグローバル名前空間の識別子を定義するようになっている。 これはインターフェイスをコールするときの簡便のためであろう。

プログラムのモジュール化を心理学実験用のプログラムでも実践すれば, 変数名の混乱によるバグは確実に減る。 それ以上に,モジュール化という行為によって自分が作ろうとしている プログラムをうまく構造化する必要に迫られ, より整った見通しのよいプログラムを作るようになるだろう。 モジュール化についての詳細はHSP付属ドキュメントの中の 「モジュール機能ガイド」 (module.htm) を参照するとよい。 このドキュメントは上級者向けと示されているが, 心理学実験のプログラムを組むには必須だと思って読むべきだ。 また,ウェブ上に公開されているモジュールは自分でモジュールを作る際の参考になる。 利用するだけでなくソースをのぞいてみるのがよい。 HSPのモジュール機能の動作について不明な事柄がある場合は, 上の例のようなプログラムで確かめてみるとわかる。

  1. first written on 2004-11-10
  2. last modified on 2004-11-15

「パーソナル・コンピュータによる心理学実験入門」に対するコメント

ついに出版された。これは,HSPを心理学実験に使おうとする仲間たちが待ち望んだ, "HSP-Psychologyリンク" を扱う初めての本である。 なりゆきとして,HSPでの心理学実験といえば世界で右に出るものはいないと自負している:-) という噂のある私が,この本について何も言わないわけにはいかないだろう。 まわりの要望もあるようなので。

なにはともあれ,HSPが主眼にあるので,ここではこの本の第6章についてだけしか書かない。 時間があれば他の章についても書こうとは思うので,コメントは順次追加されていくかもしれない。 しかし,他にもたくさん本があるような内容の章が一番優先順位が低い,と思っていただきたい。

いろいろなことをいろいろな口調で書くが, 後に行くほど多くの冗談やアラ探しやあげ足取りに近い内容が含まれており, ユーザが本気で気にしなければならないのは最初の「完全な誤り」くらいである。 「ちょっとおかしい」は首をかしげろサインがにじみ出ているところ。 もしHSPの資格検定試験が存在して私が採点者ならば減点対象にするかもしれない。 しかし,「完全な誤り」ほど事態は深刻ではない。 「厳密に考えると気になる」はプログラミングやコンピュータに関する諸々の 知識を踏まえた方が見れば疑問符をつけるかもしれないところ。 ほとんどヒヤカシなので初心者は読まなくて結構。 「もっと書いて欲しい部分」「全体的なコメント」 はほんとうにコメントである。

スクリプトの記述スタイルについては,その手の話はたくさんあるので,ここではとやかく言わない。 しかし,本を見るとある程度のスタイルは読み取れるのだが,それが一貫していないところがあるのは どうしてだろうか?

なお,誤植の類についてはここでは扱わない。

完全な誤り

p.88 必ず「定義ファイル」が付属しており, 開発中に限ってこれを開発環境の「common」ディレクトリに置かなければならない

まず,『必ず「定義ファイル」が付属しており』だが,そんなことはない。 #uselib を含んだ *.as ファイルが付属していないプラグインもある (おおっぴらに公開されているものにはたいてい付属しているとは思うが)。 もちろん,付属させなければならないというルールもない。 また,本書の文脈によって,「これは標準添付のプラグインに限った話だ」 という弁解による著者の逃げ道も塞がれてしまっている。

そもそも定義ファイルとは呼ばない。これを定義ファイルと呼ぶ人がいるか某検索エンジンで 調べてみたところ,ざっと見た感じActiveBasic3でHSPプラグインを作る, という内容のページを書いてらっしゃる方お一人だけだった。 付属マニュアルではインクルードファイル,ヘッダファイルという記載がある。 webではヘッダファイル,もしくは単にasファイルと呼ばれているようだ。

次に,『開発中に限ってこれを開発環境の「common」ディレクトリに置かなければならない』だが, 『開発中に限って』というのはコンパイルしてしまったらもう要らない,という意味だろう (あえてそう取ろう)。これは正しい。 しかし『「common」ディレクトリに置かなければならない』は正しくない。 #include が見つけられるところにあればよい。

欄外. websiteが閉じられてしまったこと。

出版社からの圧力か自主的か。あそこまでばっさりいくとかえってスッキリという見方も。

ちょっとおかしい

p.87 MIDIファイルやDLLなど,PACKFILEに追加できないファイルもあるので

これは著者の責任ではない。たしかにマニュアルにも「埋め込むことができません」とある。 しかし実際には埋め込めないのではなくて,埋め込んでも普通には(画像やwavのようには)使えないという ことをマニュアルは伝えたいのだと思う。関連して,p.97の項も参照。

p.88 プログラムの1行目には必ず「#include」に続いて

必ず1行目でなくてもいいだろうに。(冗)

#include は何行目に書いても動くし,#include より前に何が書かれていても, 何かのルーチン(ループで刺激を数回提示するとか)があっても,構わない。

pp.89,91,96など fontpicloadsndloadの第○引数のズレ (第2,第3,…引数を第1,第2,…引数と書いている)

誤植かとも思ったが,一貫してこのような表記をされているので, どうやら著者にとってはこれらの命令の第1引数(いずれも文字列)は引数でないらしい。 否,それも引数です。

話ついでに,「引数」という語については第5章で紹介されているのだが(pp.61-62), HSPのマニュアルではパラメータと呼んでいる(マクロは別)。おそらくこれは意図的で, 「引数」などの初心者にとって難しそうな語を使わないという, HSP開発上の理念にもとづくものだと思われる。 よって,本の構成のせいであろうけれども, 本書はHSPをより難しそうに紹介することになってしまっている。 これでは私が初めてプログラミングに手を出そうとする学生にHSPを勧める 理由から離れてしまう。残念。

p.97 sndload命令・mci命令のいずれを使用する場合も,実行ファイル実行時には ロードすべきファイルそのものが必要である。したがって,ロードするファイルをPACKFILEに 含める必要はない

筆者が言いたいのは,実行ファイルへ埋め込んでもロードされないということだろう。 しかし,"絶対に" 実行ファイルとは別ファイルでAVIやMIDIを用意しなければこれらは 再生できないかというと,そんなことはない。 埋め込んだAVIやMIDIを再生する方法はある。しかもプラグインなしで。

PACKFILEに含めるかどうかは,著者が他の箇所で書いていることのような, 別の基準で判断されるべき。

p.100 表6-1に掲載されていないキーの押下を検出するには TimeExp.hpi 等のプラグインを用いるとよい

getkey はどこへ行ったのでしょう? 同時に2つ以上のキー押下を検出したいのか? 百歩ゆずってそうだとしても,プラグインはいらないと思う。 getkey でできないくらいトロイならそんなPCで実験する前にグレードアップを考えましょう。 ろくなことにはなりません。

p.100 randomizeを使ってない

これは教えなくてよいのか? 原稿の都合があっても削除するのはまずいのでは。

厳密に考えると気になる

もちろん著者はわかっていつつも紙面の都合上その程度の説明にとどめた可能性が十分にある。 笑えないネタ(より深い学習のための手がかり)として読むくらいの心構えにしてください。

p.85 変数型

厳密に言えば,これは型ではない。バリアントと言うべきか。 JavaScriptやVBSの変数もそんな感じだ。それと注意,値には型がある。

p.86 式の評価の優先順位

HSPは式を「評価」するのだろうか,Cのように? HSPの算術演算はCのような「式」ではないと思う。

p.87 戻り値

statは厳密には戻り値ではなかろう。 それ以前に,こんな(初心者には)難しそうな言葉あえて持ち出さなくてよい。 戻り値なんて言葉は,付属マニュアルではHSP拡張プラグインの作成方法のところと objsend のところしか出てこない。 値として評価できるサブルーチン概念(関数)を持つプログラミング言語を 知っている人でないと本来の戻り値の意味はわからないから。

p.87 PACKFILEテキスト

PACKFILEがテキストだなんて誰が決めたのだろうか。 現在のバージョンではたしかにPACKFILEの中身は文字コードしかないように見えるが, マニュアルにはテキストファイルだとは書いてないし, テキストエディタか何かを使って手で修正してよいとも書いてない。 標準エディタのPACKFILE編集機能を使うように勧めてある。 これってやっぱりフォーマットの保証はしないってことでは?

p.88 インクルード(結合)

なぜインクルード[include]が(結合)なのか? たしかにイメージ的にはそう思い浮かべる人もいるかもしれないが教科書に書くのはどうかな。 英単語を考えればこれが奇妙なのは誰でもすぐわかる。 結合はcombineとかuniteとかconnectとかそういう語ですよ。

p.91 仮想画面とは,メモリ上に作成しておくことで操作可能な不可視画面

いや,仮想画面じゃなくても画面作成ってみんなメモリ上じゃないの?

おそらく「メモリ上に作成しておくことで」は「操作可能な」にかかっているのだと思うが, それでどう「操作可能な」理由の説明になっているのかが不明である。

p.106 プログラム6-15

es_bye はクリーンアップ関数なので明示的に書く必要がない。

もっと書いて欲しい部分

p.86 履歴付き実行機能

これが一言ふれられているだけなのはもったいない。

pp.97-100 ファイル入出力

bloadbsave の説明をしていないのは残念。 著者作プラグインの入出力命令を使うように勧めているが, bloadbsave くらいは説明してくれてもよかった。 しかも勧められたプラグインの命令もたいしたことはしていない。 これくらいなら bloadbsave を使ってスクリプト上でやってもそれほど手間ではない。

CSVに焦点を置いているのは悪くない。

全体的なコメント

たぶん原稿量(料)か何かの出版上の都合で, 「もっと書いて欲しい部分」は省略されざるを得なかったのだろう(そう思いたい)。

6.2.以降はほぼ各項ごとにサンプルがあって,しかも各行ごとにその行の命令が何を意味するかの コメントをつけているのが良い(これは私式の教授法と共通する)。もっと言えば, その命令が実験手続き上の何に対応するのかがわかるくらいのコメントになっていればよかった。 ただ単にウェイトのところに「時間待ち」とコメントしてあるのでは,どっかの診療室で 「ダメなコメントの書き方」に挙げられてしまうだろう。

心理学実験を念頭に置くということで,マルチメディア・タイマやDirectXにもふれているのは良いことだが, ある意味,これは当然。それらを使わない場合と比べるとどれくらい違うのか,とかをデモする サンプルがあるともっとよかった。

一番残念なのは,せっかくHSPを扱っておきながら,HSPの良いところをほとんど強調していないことだ。 (逆に悪いところも書いていないが。) 本の中では複数の言語が扱われているわけだし,別の言語よりもHSPのほうが良いとか悪いとか, HSPはこの点である種の実験に向いているとか,そのような言及をして欲しかった。 (著者はそのような点は無いと思ってらっしゃるのか?) それがなければ学生にHSPを勧める道理がないし,学生もHSPを選ぼうとしない。

最後に。文章がサンプルを追っているだけのところもあって多少説明不足の感があるが, 実際に(社会的認知)実験を組むにあたって最低限必要なところはしっかりすくい上げているようである。

全世界のHSPユーザを取りまとめている著者がお書きになった本なのに, 私ったらこんなコメントでよいのだろうか・・・。

  1. written first on 2004-10-06

SPYライブラリ

SPY-onlineに残ってるかも.