Hatena::ブログ(Diary)

Alone Like a Rhinoceros Horn

2009-04-22

HyperCardノート -- HyperTalk [3] -- データ型

HyperTalk について、英語版 Wikipedia をダシにノートを作成。(前回

データ型

HyperTalk - Wikipedia, the free encyclopedia


Data types are transparent to the user, conversion happens transparently in the background between strings and numbers. There are no classes or data structures in the traditional sense; their place was taken by special string literals, or rather "lists" of "items" delimited by commas (in later versions the "itemDelimiter" property allowed choosing an arbitrary character).

想定ユーザーを beginning programmers と設定した結果として、HyperTalk においてはデータ型というものが意図的に排されている。そしてそれは、Ruby変数には型がない、などというレベルの話ではなく、本当にない、ないに等しい。

Ruby においては、たとえ変数に型がないにしても、値には型がある。値(オブジェクト)に対して、お前の型(クラス)はなんなんだ? と尋ねることができるし、また値(オブジェクト)はそれに応答する能力を持つ。

一方、HyperTalk においては、変数に型がないばかりでなく、値にも数値と文字列以外のデータ型がない。そして、数値と文字列は必要に応じて暗黙裡に変換されるので、ユーザーにとってはデータ型という概念が本当に、ないに等しい。

いくら想定ユーザーが beginning programmers だからといって、何もそこまでせんでも、というぐらい思い切った設計で、本当に、配列さえないのである。ユーザーは値の型について何も考える必要はない。なぜなら、

値はすべて文字列だから

である。

擬似的な配列

値はすべて文字列、という究極(?)の一様性を獲得した HyperTalk であるが、かといって、配列ハッシュなどのデータ型(データ構造)の必要性を認めなかったわけではない。そこで、文字列を擬似的に配列のように、あるいはハッシュのように使うための「チャンク式」という仕組みが用意されている。

参照

get word 3 of "foo bar baz" --> "baz"
get item 3 of "foo,bar,baz" --> "baz"
get line 3 of "foo" & return & "bar" & return & "baz" --> "baz"

get item 2 of word 3 of line 5 of textData

代入

put "hoge" into word 3 of textData
put "hoge" into item 3 of textData
put "hoge" into line 3 of textData

put "hoge" into item 2 of word 3 of line 5 of textData

この word x of var, item x of var, line x of var という書式により、文字列を擬似的に配列のよう扱うことができる。item x of line y of var という風に組み合わせれば多次元配列のようなこともできる。*1

ありがちな言語

var[2][5]
var[2][5] = value

HyperTalk

get item 5 of line 2 of var
put value into item 5 of line 2 of var
擬似的なハッシュ

文字列の検索を行う offset関数を使って、ハッシュもどきのようなこともできたと記憶している。例えば、

foo,hoge
bar,hage
baz,moge

のような文字列 str に対し、

  1. offset(key & ",", str) でキーのオフセット値 x を求める
  2. the number of lines of char 1 to x でキーのある行 y を求める
  3. item 2 of line y of でキーに対応する値を得る

という泥臭い流れでキーに対応する値を取得することができた。*2

考察

上記の例などは、今にして思えば実に涙ぐましい(そして泥臭い)創意工夫だと思うのだが、HyperTalk でスクリプトを組むものは誰もみな、こんな風にしてただの文字列を配列とみなしたり、連想配列とみなしたり、あるいは構造体とみなしたりしながら、すべては文字列という制約の下でアルゴリズムを表現していた。

すべては文字列、というのは確かにシンプルだ。覚えなければならないことは極端に少ないし、自分も beginning programmer として HyperTalk を学ぶにあたって、型に関することで躓いた記憶はない。

しかし、自分の感覚では、この「すべては文字列」という一様性は、その恩恵よりも代償の方が大きかった気がする。恩恵としての理解のしやすさを享受できるのは、学び始めのときだけで、大体のことを覚えて言語を使い出す段になると、すぐにその制約にぶつかる。アルゴリズムを表現するために、チャンク式を駆使して文字列を配列のように使ったり、連想配列のように使ったり、構造体のように使ったりしなければならない。言語の制約がそれを要求してくる。ユーザーにそういう泥臭い工夫を強いるあたり、果たして本当にユーザー・フレンドリーなのかと大いに疑問。

そういう意味では、ユーザーがすぐに限界にぶつかる懐の浅い言語だったと思う。

せっかくオブジェクトがメッセージをやりとりするようになっているのだから、データ型に関する一様性は捨てて配列ハッシュを用意し、ユーザーがクラスも定義できるようにしておけばよかったのに、と思う。

HyperTalk のインタプリタRubyPython のそれで置き換えたような HyperCard があれば、いい感じのものができる気がする。自分が感じていた限界、制約を取っ払った、理想の HyperCard ができるんじゃなかろうか。*3

*1:しかし、やっていることは泥臭い文字列探索。文字列を頭からスキャンしての要素のカウントアップなので、当然本物の配列より遅い。

*2:全然ハッシュじゃないけどw しかしまあ、連想配列と強弁できなくもないかと。

*3:というようなことを考える人は他にもいるみたいで、PythonCard は既に存在する。

2009-04-18

HyperCardノート -- HyperTalk [2] -- 文法

HyperTalk について、英語版 Wikipedia をダシにノートを作成。(前回

文法

HyperTalk - Wikipedia, the free encyclopedia


The main target audience of HyperTalk was beginning programmers, hence HyperTalk programmers were usually called authors, and the process of writing programs was called "scripting". HyperTalk scripts are fairly similar to written English, and use a logic structure similar to the Pascal programming language.

HyperTalk の想定するユーザーはプロのプログラマーではなく、そもそもプログラミング自体が初めてというような人々。なので、その文法はなるべく自然言語としての英語に近くなるように設計された。

この、自然言語としての英語に近い文法、というのはかなり徹底している。その徹底ぶりを、ありがちな言語のそれと比較してみる。

代入

ありがちな言語

var = value

var += value
var -= value
var *= value
var /= value

HyperTalk

put value into var

add value to var
subtract value from var
multiply var by value 
divide var by value 
アクセサ

ありがちな言語

object.get_property
object.set_property(value)

HyperTalk

get the property of object
set the property of object to value
ループ

ありがちな言語

for (i = 0; i < 10; i++) {
}

while (foo == var) {
}

until (foo == var) {
}

HyperTalk

repeat for 10 times
end repeat

repeat with i = 1 to 10
end repeat

repeat while foo = bar
end repeat

repeat until foo = bar
end repeat
考察

英語として自然な書き方に近付けるために、文法はあえて(プログラミング言語としては)冗長なものにする、というのは Perl などとはまさに対極にある考え方だと思う。

ただ、HyperCard からステップアップして他の言語をも学び、それに慣れ親しんだ今となっては、正直この冗長さはどうかと感じる。ありがちな言語のコンパクトな書き方の方がすっきりしていると感じるし、きれいだと思う。C や LispRuby を学び、それらを使ってコードを書いているうちに、自分自身のコードに対する審美眼がそのように変わってしまった。

率直に言って、HyperTalk は今でも使いたい言語、ではない。今から何か新しいものを作るとして、その開発言語として HyperTalk と Ruby のどちらかを選択できるのであれば、自分は間違いなく Ruby の方を選ぶ。仮に、HyperTalk が Ruby と同等の言語機能を持っていたとしても、である。

結局、これは言語がユーザーのスキルレベルを想定してしまったことの帰結なのだろう。HyperTalk はその想定ユーザーを beginning programmers としている。確かに、誰でも最初は beginning programmers なのであるが、いつまでも beginning programmers であり続けるわけではない。そして、HyperTalk は文法まで、その想定ユーザーにあわせて設計しているために、beginning programmers であり続けない限り、(何の疑問も感じずに)使い続けることは難しいのだ。

つまり、言語に限らず、ユーザーのスキルレベルを想定するものはなんでも、成長するユーザーがそこから卒業することを、覚悟しなければならないということだ。

2009-04-14

HyperCardノート -- HyperTalk [1] -- 開発者、想定ユーザー

HyperTalk について、英語版 Wikipedia をダシにノートを作成。

開発者

HyperTalk - Wikipedia, the free encyclopedia


HyperTalk is a high-level, procedural programming language created in 1987 created by Dan Winkler and used in conjunction with Apple Computer's HyperCard hypermedia program by Bill Atkinson.

HyperTalk という言語を設計したのはダン・ウィンクラーという人物。てっきりビル・アトキンソンが設計した言語だと思っていた。*1引用した箇所の表現、created ってのが言語仕様をデザインしたという意味なら、インタプリタの実装にはビル・アトキンソンも関わっているのかも知れないが、詳細はわからない。

ただ、HyperTalk のインタプリタHyperCard とほぼ一心同体*2の関係にあり、インタプリタだけを切り離して開発したとも考えにくいので、ビル・アトキンソンインタプリタ実装にノータッチということはあり得ないだろう。

想定ユーザー

The main target audience of HyperTalk was beginning programmers, hence HyperTalk programmers were usually called authors, and the process of writing programs was called "scripting". HyperTalk scripts are fairly similar to written English, and use a logic structure similar to the Pascal programming language.

HyperTalk の想定するユーザーはプロのプログラマーではなく、そもそもプログラミング自体が初めてというような人々。なので、その文法はなるべく自然言語としての英語に近くなるように設計された。

*1HyperCard の開発者というとビル・アトキンソンということになっているし、ビル・アトキンソンといえば QuickDraw をほぼ一人で書いてしまうような人物であるので、言語ぐらい普通に作るだろう、とごく自然に思うのも無理はない。

*2:当初から HyperCard の組込み用言語としてデザインされているのは明らかで、インタプリタだけを分離して使うということがそもそも不可能な設計になっている。例えば、ハンドラ(メソッド)の探索経路として GUIツールキットのイベントメッセージ委譲チェーンをそのまま使っており、GUIツールキットを前提しなければメソッドの探索さえできない。

2009-04-11

end について

でっていう雑文。

Ruby の、

def foo
  while bar
    if baz
    end
  end
end

なんてのを見て、end end end が見た目的になんだかなー、という人がいる。自分はこれを大変すっきりしている、美しいなあ、と感じるのだが、この手の審美的評価ばかりは、評価者の……

そんなことはどうでもいい。いきなり話が脱線した。

このどうでもいい雑文において自分が書きたかったことは、Ruby って自分と相性いいかも、と思わせた要素のひとつが、この end だったってことだ。そうそう、そのことを書きたかった。自分が最初に覚えたプログラミング言語が C/C++、Java あるいはその系統の構文を継承した言語のどれか、であったなら、自分も end に違和感を覚えたかも知れない、という話。

自分が最初に覚えたプログラミング言語HyperTalk といって*1、Mac OS X 以前の古い*2 Mac にバンドルされ、「偉大なるプログラミングの砂場」を提供していた HyperCard という、オーサリングツールだか RADツールだかデータベースだかよくわからないソフト*3の組込みスクリプト言語だった。

HyperTalk - Wikipedia


HyperTalk(はいぱーとーく)はHyperCardに用いられるプログラミング言語インタプリタ方式を採用するスクリプト言語で、その文法は英語に近く、初心者にもなじみやすい。HyperCard開発チームのダン・ウィンクラーがデザインした。拡張性を考え、XCMD(外部コマンド)とXFCN(外部関数)という機構も用意され、プラグイン的に機能を追加可能である。


HyperCardオブジェクト指向環境の為、それぞれのスクリプトは、HyperCardのスタック上のオブジェクトであるカードやボタン、フィールドなどのパーツ(オブジェクト)に付随する。

この HyperTalk の文法*4がまさに制御構造を end で終わらせるタイプで、上の Ruby の例を HyperTalk で書くとこんな感じになる↓

on foo
  repeat while bar
    if baz
    end if
  end repeat
end foo

Ruby の end end end を見て、すっきりしてる、美しい、と感じる理由もよくわかるというもの。HyperTalk では end の後に、何の end かまでを明記しなければならないのだ。これはこれで、一体これは何に対する end なのだ? というわかりにくさは発生しにくいものの、正直冗長な感じは否めない。特に、ハンドラの名前(foo のところね)を変えるとそれにあわせて end のところも修正しないといけなかったりして、さすがにそれはどうなんだと疑問に思っていたわけだ。

それで Ruby の end を見たら、そりゃ、すっきりしてると思うだろ。

なので自分の場合、

  1. 初めて覚えたプログラミング言語が制御構造を end で終わらせるタイプだった
  2. しかもそれが Ruby のそれより冗長なものだった

ってのが Ruby の end をすっきりしてる、きれいだ、と感じる最大の理由かなあ。実際、初めて Ruby のコードをみたときの感想って「お、なんかこれ HyperTalk に似てるかも*5」だったし。

なんというか、最初に覚えた言語の呪縛ってものがかなり強烈だったんだろうなあ自分の場合。やることなすこと、いまだに HyperCard に引きずられまくってる。新しい、HyperCard のようなもの、いまだに欲しいし。

*1:マイナーでサーセンw というか、自分のプログラミング言語経歴って HyperTalk → AppleScript → C → Objective-C → Ruby なんだけど、なんというか、ねえw

*2:といってもそんなに昔の話じゃない。自分が HyperCard にハマったのは 2000年以降の話だし。

*3:よくわからないってのは作ってる本人たちにとってもそうだったようで、開発当初のコードネームは WildCard だったとか。HyperCard のクリエータコードが WILD なのはその名残らしい。

*4:HyperTalk の文法自体がどの言語の流れを汲むものなのかはわからない。end あたりは意外と Ruby と祖先が同じだったりしてw

*5:実際に似てるのは上っ面の雰囲気だけだけどw いや、しかし HyperTalk に組込みの配列ハッシュがあり、クラス定義ができてクロージャも扱えるようになってれば、かなり Ruby に似た言語になるような気も、しないではない。

2009-04-07

HyperTalk の repeat文の刷り込み?

loop do
end

とすべきところを、どういうわけか

while
end

とやってバグを作り込んでいた。しかも、while の次のステートメント(ループの条件式と見なされていた)が真と評価できるものを返していたせいで、これが数週間もテストを通っていた。おいおい(;^ω^)

コードをいじった結果として while の次のステートメントが場合によって偽と評価されるようになり、テストがコケてくれたことでようやく(ついさっき)問題が発覚した。

スタックトレースから簡単に問題の位置を特定できたものの、これがまたなかなか気付かないw while をいくら凝視してもそれがおかしく見えないという。loop do の存在も完全に頭から消え去っていた。やばい。

しかしなんでまた無意識のうちに、「条件式を省いたら無限ループ」てなことをやってたんだろうか。

思い当たることといえば、自分が初めて覚えたプログラミング言語である HyperTalk の repeat文?

自分がこれまでにやったことのある言語で、条件式のないループ構文が無限ループになるのってこれだけのような気がする。確か、

repeat for num times
end repeat

repeat with var = start to end
end repeat

repeat while condition
end repeat

repeat until condition
end repeat

という構文であって、

repeat
end repeat

で無限ループになったはずだ。

これはもしかして三つ子の魂百までというやつなんだろうか? 自分が最初に覚えたプログラミング言語による刷り込みの効果。

だとすると……ちょっぴり嬉しいような気も。それだけの数のループを、自分は HyperTalk の repeat文で書いてきたってことなのだ。

2009-03-29

HyperCardノート -- Webブラウザとの類似性

HyperCard とは何か、という問いに対し、しばしば「ハイパーテキストを実装した最初の商用ソフトウェア」といった説明がなされる。

HyperCard - Wikipedia


HyperCardは、ハイパーテキストを実現した最初の商用ソフトウェア。1987年にアップルコンピュータ(当時・現アップル インコーポレイテッド)のビル・アトキンソンが開発した。Macintosh(Mac OS)で動作し、ゲームの制作、簡単なプログラムの開発等に利用される。

HyperCard、HyperTalk の hyper もそこからきてるわけだから、まあそれは至極妥当な説明だと思うんだけど……

しかし、当時 HyperCard と Internet Explorer を同時に使っていて、そこに hyper text という共通項があることに、自分はまったく気が付かなかった。というか、HyperCard と Webブラウザが似てるなんてことも(当時は)全然思いもしなかった。

HyperCardWebブラウザ
ノードカードページ
スキームスタック*1HTML
リンク主にボタン主にテキスト
スクリプト言語HyperTalkJavaScript

抽象化していけば、両者はかなり構造的に類似したものがあるのに、使ってみるとその使用感は全然違う。その感覚的相違はどこから生じるのだろうか。

自分なりに考えてみると、それは (1)プログラミングのための道具 と (2)閲覧のための道具 の違いだろうか。browse tool 選択時の HyperCard、あるいは HyperCard Player であれば、HyperCard はずっと (2) に近くなって、この違いはなくなる*2気がする。しかし、スタックを作るという行為と、Webページを閲覧するという行為は、全然違う。

ん? そもそも Webブラウザと比較するのが間違いか。Webサイトの開発環境と比較すべきなのかそもそも。

開発用閲覧用
HyperCardHyperCard Player
Webサイト開発環境*3Webブラウザ

ということか。

あの当時もし Webサイトの開発をやっていれば、そこに HyperCard との類似性を見出せたのかも知れないな。そして、自分は HyperCard の続きをやっているように、思えたのかも知れない。幸か不幸か、そうはならなかったが。しかし、あの当時もっと JavaScript や、サーバーサイドのことを知っていれば、自分は HyperCard の後継(互換環境)を求めるのではなくて、Webサービスの開発に新たなプログラミング環境を見出し得たのかも知れない。*4

*1:ファイルフォーマットとしてのスタック。

*2:といっても、ローカルに閉じた環境とインターネットっていう相違を抽象化したレベルでの話。

*3:自分の場合は要するにエディタw

*4:しかし、幸か不幸か、そうはならなかった。三つ子の魂百までというが、自分の場合、最初のプログラミング環境が完全にローカルに閉じた HyperCard だったこともあって、プログラミングで扱う領域がなかなかネットワークとか Web の方へは向いていかなかった気がする。そのローカル志向は実は今でも自分の中に根強い。

2009-03-22

HyperCardノート -- GUIツールキットとの対話シェル

対話シェル

HyperCard には、GUIツールキットとの対話シェルという側面がある。

GUIツールキットというのは、大雑把にいうと、(1) ウィンドウやボタンなどのコントロール(GUI部品)を描画してくれて、(2) ユーザーの入力操作に対するイベントメッセージを発行し、それを適切なオブジェクトに dispatch してくれる、イベントドリブンなプログラミング環境を提供するライブラリなり OS の機能である。というか、ここではそういうことにする。

旧 Mac OS の場合、UNIX のように OS とウィンドウシステム(GUI)が分離されていなかったのでわかりにくいけれど、HyperCard の対話の相手であった Toolbox(の一部)は、機能的には確実にその GUIツールキットの範疇に入るものだ。もし UNIX上で HyperCard のようなものを作るとしたら、Toolbox に相当する部分は確実に Gtk+ なり Qt なり wxWidgets なりになるだろうから、そこははっきりしている。

HyperCard のユーザーは、button tool や field tool、あるいは set the style of cd btn 1 to ... などのような HyperTalk の命令を通して、GUIツールキットとしての Toolbox と対話をしていた。スタックを作る過程というのは GUIツールキット(Toolbox)との対話セッションともとらえることができ、その対話の仲立ちをしている HyperCard をシェルととらえることはそんなに奇抜な考え方でもないだろう。

旧 Mac OS におけるシェルといえば Finder で、どちらもユーザーと Mac OS との対話インターフェースを提供するものだが、両者は OS とウィンドウシステムが非分離な旧 Mac OS において、対話の相手とする OS の機能部分が違う。Finder は、UNIX における bash など、いわゆるシェルに相当するもので、HyperCard はそれよりもっと上位の、ウィンドウシステムのレベルの domain-specific なシェルだ。

シェル対話の相手
bashなどOS(カーネル)
FinderOS(カーネル)
HyperCardGUIツールキット
スタック

スタック作成を GUIツールキットとの対話セッションととらえると、ファイルとしてのスタックは対話セッションのログ、対話セッションの内容をシリアライズ(永続化)したものと考えることができる。

ウィンドウがあって、その大きさはこれくらいで、ここにボタンがある。ボタンのラベルはこうだ。そして、それを押すとこうなって…… そしてその横にはフィールドがあって…… という対話セッションの内容がシリアライズされて、スタックというファイルフォーマットに収まっているいる。次回、そのスタックを開いたときにはその対話セッションが再生されて、セッションで申し合わせた通りの GUI が再現される。

そう考えると、スタックというのはシェルスクリプトに相当するものともいえる。その作成過程自体が対話的になされるのでわかりづらいが、やっぱりそれは対話の相手に対する命令の羅列であり、それを永続化したものだ。