コンセプト別の解説
テクスティオは次のようなコンセプトをもって作られています。
- 短く書きたい
- 複数の書き方は少なくしたい
- 覚えることは少なくしたい
- 文脈で機能を変えたい
- 適切な既定値を指定したい
- 既存のツールに依存したい
- 他の言語と似せたい
それぞれのコンセプトについて詳細に説明します。
短く書きたい
タイピング数を減らせば楽に書けるから、プログラミングに使う単語を短くしよう、というのは簡単に思いつきます。
この方針は、キーボードでコマンドを打ち込む CUIによるOSのコマンドに色濃い文化です。
例えば、ファイルのリストを表示するコマンドは、file list
とかになりそうなものですが、ls
と2文字のコマンドが割り当てられています。
list
ではまだ長い、あと2文字減らしてls
にしようとか、涙ぐましいほどの 省力化努力です。
現在のプログラミングでは、ツールのサポートにより単語を全てタイプしなくても予測変換してくれます。
そして、使われる単語(制御構造・命令・オブジェクトなど)が膨大であるため、短い単語はすぐに使い切ってしまうし、そもそも短い単語だと何を意味する単語か分からなくなってしまいます。
そのため、多くのプログラミング言語は、単語が長くなっても読んでわかりやすい名前を付けよう、という方向に進んでいます。
その方がプログラムを読んだときに分かりやすく、結果的に楽だ、という思想です。
テクスティオはこの潮流に逆行していて、極力短い単語を使うようにしています。
まず、コーディングに使うツールはXMLが書けるものならなんでもいいという方針を取っているので、単語の補完は期待できません。
そして、使う単語数を極限まで減らすという方針を取っているので、全ての単語を覚え切ることができます。
ならば、短い単語であったほうが楽、という結論になります。
複数の書き方は少なくしたい
例えば、いくつかの言語では行末に;をつけても良いし、つけなくてもいい、というような仕様があります。
一見、意味がわからない仕様ですが、C言語系の行末に ; をつける言語は非常に多く、その作法がそのまま使えるというのは「(C言語系が使える人にとって)学習が楽」という言語にとって大きなメリットとなります。
しかし、; で行を区切る方式は、コンピュータのリソースが限られていた時代の名残でしかありません。
というのも、昔は画面に表示できる文字数が少なく、改行を頻繁に入れていては、画面上に表示できるコード量が少なくなって、見通しが悪くなってしまいます。
例えば昔は80文字×25行あたりが普通でしたが、今は300文字×100行とかの表示ができる環境も珍しくなく、むしろぎっちり文字を表示したほうが見通しは悪く、適度に行を開ける空行も使ったほうが理解しやすいくらいです。
そんなわけで、盲腸的な行末の ; は、つけてもつけなくてもいい、という仕様になっているわけです。
しかし、こういう「どっちの書き方でもいいですよ」というのは、自由といえば聞こえはいいですが、「どっちで書いたらいいか分からない」という迷いポイントを産みます。
自由は不安なのです。
自由は面倒臭いのです。
どーでもいいところは人に決めておいて欲しいのです。
ということで、テクスティオ独自の仕様では複数の書き方ができるという部分は少なめです。
とは言っても、テクスティオはXMLを採用しているので、ガチガチに書き方が決まっている、というわけではありません。
XMLの仕様がかなり自由に複数の書き方を許容するので、結果的にテクスティオもそれなりの自由度を持つことになっています。
覚えることは少なくしたい
多くの言語は汎用性(なんでもできるということ)を重視するので、結果としてその仕様は膨大なものになります。
そして現在主流のオブジェクト指向言語(OOP)は、言語全体を把握している人は世界に一人もいないのではないか、というくらいに巨大化しています。
その全体を覚え切ることは勿論できるわけはありませんし、最低限必要な手続きであっても、かなりの量になります。
テクスティオは、iFに用途をフォーカスすることで、極力覚えなければいけないことを減らしました。
また、前述の「複数の書き方は少なくしたい」で書いたように、仕様に柔軟性を持たせないことで、全体の仕様サイズをコンパクトに保っています。
さらに、<at>
とat=
のように、要素名と属性名を共通化することで、覚えなければならない単語数を減らしています。
それに加え、要素の配置や内容を持つ持たないといった文脈により機能を変えることにより、ひとつの単語で複数の機能を実現し、単語数を減らしています。
他にも、数値は整数値しか使えないなど、必要ない(と私が判断した)機能は、バッサバッサと切り捨てています。
どうしても必要機能があるなら、別の言語使ってください、という割り切りです。
割り切りができずに汎用化しようとすると、結局なんに対しても使えない駄言語ができあがる、という危惧が強くあったからです。
文脈で機能を変えたい
先ほどの「覚えることは少なくしたい」でも書きましたが、テクスティオは同じ要素でも文脈によって機能が異なります。
XMLはいろいろな表現方法があるのですが、表現方法ごとに機能を変えれば「複数の書き方は少なくしたい」というコンセプトも満足できます。
例えばXMLでは、<p></p>
という書き方と<p/>
という書き方は同値です。
テクスティオでは、せっかく形が違うのですから、機能も変えたいという考えで作られています。
そのため、例えば同じ名前のxという要素(属性)でも、配置位置や、内容・id属性のあるなしによって以下の7種類に機能が変わります。
種類 | 構文 | 配置 |
---|---|---|
命令 | <x/> | act,option |
包含 | <x>内容</x> | 主にact,option |
定義 | <x id="識別子">内容</x> | textio |
召喚 | <x id="識別子"/> | act,option |
設定 | <x id="識別子">内容</x> | act,option |
置換 | <x id="識別子"/> | p |
条件 | <e x="条件式">…</e> |
こうすることで、<p></p>
という書き方と<p/>
という書き方は、別ものとして定義されます。
機能は違っても名前は同じなので覚える単語は減りますし、それぞれの機能は深い関連性を持たせているので、すっと理解できます(よね)
そもそも、自然言語は同じ単語でも文脈によって意味が変わるのが当然なので、多くのプログラミング言語の持っている「どこで使っても同じ機能」というコンセプトの方が不自然と言えます。
さらに、オブジェクト指向言語でいうポリモーフィズムの考え方を採用しており、上記の使い分けは全ての要素で可能です (要素ごとに使える機能の種類は異なります)。
actの召喚要素は<act id="識別子"/>
なのに、pだと<p method="call">識別子</p>
、などということはありません。
pでもやはり<p id="識別子"/>
と、召喚要素は同じ形で書けます。
このように、操作を共通化し一貫性を持たせることで覚えることを減らし「この要素も同じ使い方ができないかな?」と予測することができます。
例えば、次のように機能ごとに接頭辞をつけるような仕様も考えられます。
こちらの方が機能ごとに名称が区別されていて明快だ、という判断もありですが、テクスティオでは採用しませんでした。
種類 | 構文 |
---|---|
命令 | <commandX>内容</commandX> |
包含 | <x>内容</x> |
定義 | <functionX id="識別子">内容</functionX> |
召喚 | <callX id="識別子"/> |
設定 | <setX id="識別子">内容</setX> |
置換 | <replaceX id="識別子"/> |
条件 | <e ifX="条件式">…</e> |
他にも書き方は考えられますが、いずれにしろ冗長になり、覚えなければいけない単語も増えています。
そもそもXMLとして書式で機能が変わっちゃダメだろ、という意見も尤もですが、テクスティオではあえて、そのルールは破りました。
逆に更に進めて、識別子を全要素共通にして、識別子を要素名にすれば、もっと短く書けるかもしれません。
種類 | 構文 |
---|---|
定義 | <識別子>内容</識別子> |
召喚 | <識別子/> |
設定 | <識別子 v="内容"/> |
置換 | <識別子/> |
しかし、識別子が要素名としても使えるとなると、識別子と要素名の衝突がおきます。
そこで、要素名の衝突を避けようとしてネームスペースで区別すると、極力短く書きたいのに本末転倒です。
また、識別子だけではその内容がどの命令に属するものか(他の言語で言うところの型)が分かりません。
短くは書けても、解読が困難になってしまうと考えて、テクスティオでは避けました。
以下は参考までにXSLTでの実装例です。
種類 | 構文 |
---|---|
命令 | <xsl:apply-templates/> |
包含 | <xsl:apply-templates>内容</xsl:apply-templates> |
定義 | <xsl:template name="識別子">内容</xsl:template> |
召喚 | <xsl:call-template name="識別子"/> |
設定 | <xsl:variable name="識別子" select="内容"/> |
置換 | <xsl:value-of select="$識別子"/> |
条件 | <xsl:if test="条件式">…</xsl:if> |
適切な既定値を指定したい
最初から設定されているもので十分なら、コード自体書く必要がありません。
コードがないことが、もっとも短いコードであり、究極はコードを一切書かずにゲームを作りたい、という怠け者思想です。
例えばフラグの既定値はfalseです。
ゲームの場合、大抵はフラグが立っていないfalseの状態が初期状態なので、そこをいちいち設定させるのは 面倒だろう、という発想です。
最近の言語の場合「変数は必ず宣言して初期値を設定して使う」というのが当たり前になっています。
私もそれがプログラミング言語の正しい方向性だと思います。
しかし、テクスティオでは初期状態を明確にすることで、初期化をしないことで発生する問題はある程度解決すると判断しています。
また、宣言なしで使える変数は、タイプミスなどにより発生するバグの温床になるのですが、手続きや覚える単語が増えることを嫌って、宣言不要にしています。
ただ将来的にはオプションをonにすると、厳格に変数宣言必須に変更する、などといった対処をする可能性はあります。
この無宣言で使える変数によるバグは、かなり根深いので、仕様をコンパクトにするより大事、と思ったりもしてます。
そのほか、フォントの大きさや色なども、通常は変える必要のない既定値を目指しています。
そんなの当たり前だろうと思うかもしれませんが、例えば、既定値のままボタンを表示するとクリックできないぐらい小さい、というような既定値がイーカゲンな開発環境はゴロゴロしています。
既存のツールに依存したい
専用の開発環境(ツール)が整っている言語は珍しくありません。
しかし、新たなツールを使うには学習コストががかって楽ではありません。
できれば、すでに手に馴染んでいるツールを使いたいものです。
開発ツールの開発に時間を取られて、本体の開発が進まないとか、割とありがちです。
また、専用の開発ツールのできが悪くて、言語の仕様はいいのに開発するのが嫌になる、ということもありがちです。
そんなわけでテクスティオは記述・表示用のツールが揃っているXMLを採用しました。
XMLならば、XML記述ツールを使わなくても、テキストツールで開発することもできます。
Microsoft Wordで開発することだってできます。
多く存在するXML lintあるいは、XML Validatorと呼ばれる構文チェッカーで、XMLとしての記述の正しさをチェックできます。
例えば、コマンドラインではxmllintコマンドがOSに用意されていることが多いですし、オンラインにもW3Cが用意したW3C Markup Validatorがありますし、コードエディタには入力中に構文チェックを行ってくれるものも多く存在します。
これは安心ですね。
他の言語と似せたい
先に行末の ; の有る無しの話をしました。
既存の言語と似ているというのは、非常に「気が」楽です。
ならばテクスティオも、すでにメジャーな言語に似せていきたい、と考えるのは自然です。
XMLを採用した時点で、もうXMLという記述言語のルールに則ることになりますから、日常的にXMLを使っている人にとっては、相当に入門ハードルが落ちます。
さらにXMLの中で最もメジャーな(X)HTMLに似せれば、ぱっと見で「なんか分かりそう」という雰囲気を感じてもらえる人が断然増えます。
そこで、HTMLで使われるタグと同じものをテクスティオでも採用しています。
名前が同じで微妙に機能が違うというのは、混乱要素になりかねないところもありますが、やはりとっつき易さは捨てがたいものです。
HTMLのプログラム制御はJavaScriptで行いますが、テクスティオでもJavaScriptを採用してしまえば、それは単なるWebページになって意味はありません。
XMLでプログラムが書ける環境は、XMLでユーザインタフェースを記述して、その制御はXMLでない言語で行う、というHTMLとJavaScriptと同様のパターンが一般的です。
おそらくXSLTがXMLのみで記述されたプログラム言語で一番メジャーだと思います。
ならばXSLTに似せるのが良さそうです…が、どうもXSLTは冗長で分かりづらい。特に後述しますが条件分岐の書き方が、いかにも洗練されていない感じです。
テクスティオはiFを記述するのだから、既存のXMLでiFを記述する言語に似せるのが良い、という考えもあります。
実際XMLでiFを書く環境はあるのですが「そもそもその環境が気に入らないからテクスティオを作っている」わけなので、採用する筈もありません。
そんなわけで、制御部分はほぼテクスティオのオリジナルの記述で、他に似た言語は少ないと思います。
制御部分の言語仕様のコンセプトについては、さらに続く部分で延々解説します。
プログラム仕様各部のコンセプト
ここからは、テクスティオのコンセプトを、各部分ごとに解説します。
前述の内容とかぶる部分が多いですが、縦軸方向と横軸方向から読み解くという内容なので、説明被りはご了承ください。
要素名と属性名
以下のように要素名は短めになっています。タイプ数が少なくて済むのと、短いと英単語ではなくアイコン的な感覚で瞬時に判断できて良いという考えです。
inventory
が少々長めですが、大抵の場合、他のものと組み合わせずにinventory
要素のみ置かれるものなので、短いとちょっと寂しいし、意味が分かりにくいかなと思って、ここは長いほうがいいという判断です。
<textio>、 <act>、 <p>、 <i>、 <else>、 <select>、 <option>、 <go>、 <inventory>、 <var>、 <item>、 <at>、 <pla>
p
、i
、select
、option
、var
についてはHTMLにも存在する要素で、親しみがあるかと思って採用しています。
逆にHTMLを使ったことがない人も、テクスティオに慣れていたらHTMLに親しみが持てていいだろう、という判断です。
また、textio
要素をhtml
要素に変えると、ある程度HTMLとして表示されるので、製作中の確認に便利かもしれない、それどころかHTMLエディタである程度書けるかもしれない。
それに、HTMLエディタで書く場合に、特に設定なしに色付けされて見やすいだろう。
ということを期待してたりしますが、自分自身はそういう使い方をしていないので、あんまり意味なかったですね。
いくつかの要素名(var
,item
,at
,pla
)は、そのまま属性名として使うと条件の指定になります。
具体的には<at>
(要素)とat=
(属性)という使い方です。
at
ではなくat-test
のような属性名にするという手もありました。
しかし、同じ名前を使えば関連するものであると認識させられるし、微妙に違うものを2つ覚えさせるより同じ方がスッキリします。
さらに、単に-test
のぶん名前が短くなる、ということで同じものを採用しました。
学習コストを下げる効果は、かなりあるんじゃないかと思っています。
これも、文脈依存性の一つとして理解できる、という期待もありました。
私自身すぐに慣れ、要素名と同じ属性名が判定に使われるのが当たり前という感覚になっています。
比較演算子
プログラミング言語のコンセプトとして多いのが「こういう書き方も、こういう書き方も自由にできます」というもの。
しかしそれは「特にこう書きたいという確固とした意志」を持たない人にとっては、よく分からない選択がたくさん突きつけられるという、極めてストレスのたまる状態とも言えます。
大抵のプログラミング言語には、大小の比較演算子が<
、>
、<=
、>=
の4つは、最低あります。
しかし、A > B
は、B < A
とまるっきり意味は同じです。じゃあ、二種類用意する必要はない。
テクスティオには整数しかないので、A < 10はA <= 9と同じ。ならば二種類は必要無い。
ということで、大小の比較演算子は <=
を意味する ~
しかありません。
副次的に、右辺が大きいと真、という一貫性が生まれてコードが読みやすくなります。
比較演算子は「左辺は常に変数派」や「>
と>=
は使わない派」「範囲指定の場合に限り変数を真ん中に置く派」、さらには「整数に対しては常に<=
、>=
を使う派」などの宗教論争が激しい箇所なので、そう書くしかないという仕様は、心安らかにしてくれます。
<=
じゃなくて~
なのは、XMLベースなので、<=
を書く場合、実体参照として<=
と書くことになり、ちょっとそれは読みづらいということと、単純に短く書けるということからです。
また、テクスティオは範囲指定をする際に、項目を3つ並べて1~A~5
と書けます。
多くのプログラミング言語では、A>=1 and A<=5
のように書きますが、テクスティオの方式が断然読みやすく、書くときに迷いません。
一応、テクスティオでも1~A,A~5
とも書けますが、あえてこう書く意味はないでしょう。
テクスティオで、1~A,A~5
と書けることを許容しているのは、他の1~A,B=3
という書き方との一貫性を保証しているにすぎません。
否定演算子
ちょっとまだ、仕様が定まってないのが否定演算子(not)です。
テクスティオでの否定演算子は ! を使います。
真偽条件
iFは、かなりの率でフラグの判定を行います。
そこで、変数の真偽判定は単に変数名を書くだけで可能になっています。
例えば、<p item="アメ">アメちゃんだ。</p>
のように書けば、「アメを持っている場合」となります。
<p item="アメ=true">アメちゃんだ。</p>
とも書けますが、これは<p var="candyNum=1">アメちゃんがひとつ。</p>
のような書き方との整合性を優先したためです。
しかし、フラグチェックは頻出するので、極力短く書きたい。そこで省略記法も用意したというわけです。
変数
テクスティオで使う変数は、var
、i
、item
、at
、pla
の5つがあります。
スクリプトとしての書き方はほぼ一緒ですが、var
とi
以外はシステムでの使われ方が、だいたい決まっています。
item
で設定したものはinventory
で表示されるし、at
に設定したものは注目名詞として使われます。
pla
はat
に似ていますが、より汎用的なものです。
値を設定すれば、あとは勝手に使われるということで、システム属性(プロパティ)に近いものと言えます。
テクスティオで変数らしい変数はvar
、i
要素です。
両者の違いは、var
は数値か真偽値を設定し、i
は文字列か真偽値を設定します。
他のプログラミング言語的に言えば、型が異なるわけです。
それぞれ、真偽値も入力できるというより、実装的には判定の際にvar
だと0
がfalse
に、i
だと空文字列がfalse
に判定されるという作りになっています。
大抵の言語で、数値と文字列は真偽値として判定できるので、真偽値を別に用意する必要はないだろう、という判断です。
これについては真偽値を設定できる属性を、例えばflag
として別に用意するべきかもしれないとも思っていますが、現状var
があればほぼ問題ないので、仕様としても実装としても真偽値専用属性は存在しません。
フラグを立てる場合、<var id="flag"/>
か <var id="flag">true</var>
の2種類の書き方ができます。
true
の設定方法が2種類あるのは、falseを設定する<var id="flag">false</var>
との一貫性を持たせたかったためです。
false
を設定する書き方から想像すると<var id="flag">true</var>
と書けないと気持ち悪いので、複数の書き方は避けるコンセプトより、整合性を優先させました。
しかし、フラグ立ては頻出するので、極力短く書きたい。そこで省略記法も用意したというわけです。
テクスティオの変数は全て大域変数です。
変数の定義もなく、型指定も存在しません(型指定はvar
とi
属性の使い分けで、事実上存在しているようなものですが)
スパゲティプログラムの温床なので、最近のプログラミング言語では、なかなかない仕様です。
テクスティオの場合、大量の変数を使うことを想定していません。
そもそも製作者が混乱するほどののフラグやアイテムを用意したら、プレイヤーのほうも混乱するので、むしろ良い抑止力になると考えています。
大域・局所変数による範囲の存在や、変数の定義・型指定は、規模が大きくならないうちは、単に面倒であることが多く、プログラミング初心者がつまづく箇所でもあります。
その代わり、全変数の初期化は、<var/>
のように空要素を書くだけで簡単にできるようにしています。
区切りがあるごとに初期化するようにしておけば、変数が増えすぎて混乱することもないでしょう。
設定(代入)
多くの(C言語系)プログラミング言語では、変数への代入をx = 2
のように書きます。
個人的には、数学で比較演算子としてつかわれている=
を比較演算子として使えないのは変だと感じます。
=
を代入演算子として使ってしまったがために、比較演算子が==
になるというのは変な話です。
最初から、別の代入演算子を使うべきです。
例えば、Pascal言語の代入演算子は:=
で、これは非常に合理的だと思ってます。
ただ、テクスティオはXMLによる言語なので、代入するにしても、どこかにXML要素を使うことになります。
極力短い書き方として、<var id="x">2</var>
を採用しました。
もう一つ、<var id="x" contents="2"/>
といった書き方も考えられますが、内容を示す属性(ここではcontents)が必要になって、覚えることが増えてしまうのが難点と考え、採用を見送りました。
あとは、<var>x:=2</var>
なんかも考えられますが、こうなるとXMLの構文チェックでエラーを発見できませんし、XMLで書く意味がなくなってしまいます。
多くの言語では変数の宣言と初期化を合わせてvar x = 2
のように書くので、<var id="x">2</var>
は比較的近い形かと思います。
多くの言語ではx = x + 1
と書くと変数の値に1を加算できます。
頻繁に使う処理なので、簡単に書けるように、x++
という書き方ができる場合がほとんどです。
当然テクスティオでも簡単に書けるようにしたいと考え、<var id="x">+1</var>
という書式を採用しました。
一見、1を代入するように見えますが+が付いているので「加算」の意味が与えられています。
当然<var id="x">-1</var>
だと「減算」です。
テクスティオでは変数の変更は、ほぼ加算と減算であると考え、他の言語のx = x
の部分までは組み込まれていて、最後の+ 1
の部分だけ記述するという方式なわけです。
ここでお気づきかと思いますが、この仕様だとマイナスの数値を代入することができません。
テクスティオ(iF)でマイナスの数値を代入する必要はない、と判断しているので、そんな機能はそもそも必要ありません。
一応、<var id="x">0</var><var id="x">-1</var>
というように、いったん0を代入して減算することで負の数を設定できます。
ちなみに、整数以外の数値を扱う必要もないと判断しているので、テクスティオで使える数値は整数のみです。
それ以上のことがしたい場合は、他の言語でプログラムすればいいという割り切りで作っています。
現在の実装は少数も受け付けたりするんですが、仕様上は整数しか扱えません。
条件判定
次のコードはXMLによるプログラミング言語のひとつであるXSLTによる条件分岐の書き方です。
<xsl:choose> <xsl:when test="$x=4"><p>正解</p></xsl:when> <xsl:otherwise><p>不正解</p></xsl:otherwise> </xsl:choose>
テクスティオで書くと(目的が違う言語なので、もちろんまったく同じ意味とは言えませんが)次のようになります。
<p var="x=4">正解<else/>不正解</p>
テクスティオは、ほとんどすべての要素にvar
属性があり、var
属性が設定されていれば条件判定が行われます。
このことで、XSLTにおけるchoose
要素が不要になります。
さらにテクスティオでは、else
要素が内容に含まれると、その前後で内容を分割し、else
要素の前の部分を真(true
)、後ろの部分を偽(false
)の実行内容とします。
これでwhen
とotherwise
のように真と偽の2つの要素が不要になります。
つまり、テクスティオには基本的に条件判定のための特別な要素は存在せず、条件判定属性を追加することで要素ブロックがそのまま条件ブロックとなります。
XMLはとにかく要素によってブロックを作っていく構造となっているので、ほとんどあらゆる箇所にブロック構造が出現します。
ならば新たに条件ブロックを作らなくても、すでにあるブロックに条件を含めれば良い、という発想です。
なお、var
以外のi
、item
、at
、pla
でも同様に条件判定が可能となっています。
コマンド判定
テクスティオにおける条件判定のほとんどは、iFの肝であるコマンド判定です。
そこで、コマンド判定専用にselect
要素とoption
要素が用意されています。
ここでの書き方は、XSLTの条件判定の書き方と近くなり、次のようになります。
<select> <option verb="ミル"> <p>おかしなものはない</p> </option> <option verb="トブ"> <p>垂直跳びっ!</p> </option> </select>
ここでselect
要素に「キーボードからの入力」「コマンドの分離」「注目名詞を代替値として適用」などの諸機能が含まれます。
option
要素には「動詞と名詞のコマンド判定」「既定コマンドの割り当て」などの機能が含まれます。
特別な要素を用意することで、ゲームのコアな部分を自然に利用できるようになっているのです。
else
要素を使えばselect
要素も必要なく、スッキリ書ける気がしますが、いくつか理由があってelseは採用していません。
<!-- こういう書き方はしない --> <option verb="ミル"> <p>おかしなものはない</p> <else verb="トブ"/> <p>垂直跳びっ!</p> </option>
製作時に入れ替えを頻繁に行うので、まとまりがはっきりしていた方がいいという判断がひとつ。
それに、コマンド以外の別の判定を入れたときにまとまりが悪くなります。
<!-- もし、コマンドをelseで区切る方式だと --> <option verb="ミル" item="メガネ"> <p>おかしなものはない</p> <else/> <p>ミルを入力していないかメガネを持っていない、と判断される</p> </option>
「ミルを入力していないかメガネを持っていない」という状況判断が必要な場面が、iFにはほぼ存在しません。
テクスティオは「ほぼ存在しないもののための仕様は悪」という考えで製作しています。
テクスティオは、コマンドの判定まではoption属性内全体に影響する仕様です。
else属性で区切ってもverbやnounによるコマンド判定までは終わっている、という考えです。
次のコードを見ると、ミルを入力した際にメガネがあるかないかで見え方が違う、という判定がスッキリ書けているかと思います。
<!-- option以下はverbまたはnounの判定下にある --> <option verb="ミル" item="メガネ"> <p>おかしなものはない</p> <else/> <p>ぼやけてよく見えない</p> </option>
テクスティオでは中にact属性を挟むことを許容しています。
次のコードは、上記のactなしのコードと同じ挙動となります。
<!-- actを入れると分かり易い --> <option verb="ミル"> <act item="メガネ"> <p>おかしなものはない</p> <else/> <p>ぼやけてよく見えない</p> </act> </option>
iFでは「コマンド判定後に、いくつか条件で分岐する」という記述をする場面が多く、コードの分かりやすさより、コードの 短さを優先しました。
また、コードが短い方が読みやすい面もあるので、トータルでは現在のverbとnounの判定はoption属性全体に影響する、という仕様のメリットが高いだろうとの判断です。
以上を総合して、最終的にsection
要素で全体を括って、option
要素毎に独立性が高い方が読みやすい、という判断です。
あと、HTMLのsection
とoption
の仕様と同じなので、1段階のものならブラウザでポップアップメニューとして表示される、というのも多少理由にあります。
HTMLエディタで雛形が書きやすいんじゃないか、と淡い期待も…。
ただ、まーこれは、ほとんど役に立たないんじゃないかなー、気休め程度で。
一番はHTMLで見たことあるなら、少し親近感がもてる、というところでしょうか。
判定属性
判定のためにvar
、i
、item
、at
、pla
、noun
、verb
の属性があるのは少々無駄ではないか、という考えもあります。
例えば、if
という属性を作って、全部そこに判定を任せてしまえばスッキリするのではないか、というわけです。
しかし、そうすると例えば、次のように判定文の中に、何を判定するのかを書かなくてはいけないし文字列を囲む記号が別に必要になりますし、むしろ書式は冗長になります。
<p if="item='エンピツ',at='ツクエ'">そうだ、メモを残しておこう。</p>
実は、最初から判定対象ごとに別れている方がスッキリかけます。
<p item="エンピツ" at="ツクエ">そうだ、メモを残しておこう。</p>
デメリットは、初見だとそこが判定文だと分かりにくいこと。
もう一つは、後述しますが、複数の条件間の論理結合が選択できない(論理積に固定)のもデメリットです。
論理演算子
テクスティオで ,
が and
にあたり、;
が or
にあたります。
and
を&
あるいは&&
と書く言語も多いのですが、テクスティオはXMLなので&
を書く際は&
と書く必要があり冗長であること。
or
を|
または||
とする言語も多いのですが、1やlと間違いやすいということ。
and
やor
だと、単体でも文字数が増える上に、識別子と区別するためにスペースを必要とするのでさらにタイプ数が増えてしまう。
ということで「短く書ける」というのが採用理由の一番です。
,
は間を隔てるものが少ないのでより近いもの、;
は隔てるものが多いので少し遠いものという感覚で使える。
演算子の実行順としては,
を先に、;
を後に実行していることからも、,
が近く、;
は遠いというのは納得できる。
;
が|
に近い雰囲気であることも採用理由のひとつです。
英文では、項目をコンマで区切り、項目グループの区切りにセミコロンを置くという用法があり、それに準じてもいます。
他にも色々と記号がある中で、特にこれらを選んだのは、単語を併記する際の区切りとして一般的であり、かつ上記のようなand
とor
として覚えやすい特徴があるからです。
複数の属性による条件が存在する場合、各条件間は常にand
で判定されます。
例えば、item
の判定がtrue
、at
の判定がfalse
の時は、全体としてはfalse
になります。
別の言い方をすると一つでも条件がfalse
だと全体がfalse
になる、ということです。
これは、or
を使いたい場面はほぼない、という判断です。
<p item="エンピツ" at="ツクエ">そうだ、メモを残しておこう。</p>
どうしてもor
にしたい場合は、次のようにelseを使って条件を並べてしまえば実現できます。
すごく無駄な書き方のように見えますが、実際無駄です。
しかし、ほぼ使うことがないシチュエーションのために、機能を増やすことは避けたかったのです。
<p item="エンピツ">そうだ、メモを残しておこう。<else at="ツクエ">そうだ、メモを残しておこう。</p>
ひとつの属性の中ではor
(テクスティオでは ;
記号)が使えるので、ほとんど不便を感じることはないでしょう。
ループ
トップレベル(textio
要素の直下)にact
要素を置くと、そのact
ブロックはループになります。
しかしiFでは、繰り返しコマンド入力ができる、というのはごく自然なので、トップレベルのact
要素のみがループになっているという事を意識することもないでしょう。
大抵のプログラミング言語には、ループ回数などの条件を指定する部分までループ構文に組み込まれていますが、テクスティオの場合、コマンドによる条件判定がループ終了の条件であることがほとんどなので、ループ構文に条件設定部分まで用意する必要がありません。
もし、ループ回数を指定したい場合でも、var
とgo
要素を組み合わせば実現できます。
これも「ほぼ存在しないもののための仕様は悪」とういコンセプトに基づいています。
ジャンプ
テクスティオでは、go
要素を使うとジャンプが可能です。
しかし、古来プログラミングではジャンプ命令はスパゲティプログラム(ごちゃごちゃして理解不能なプログラム)の温床として、忌み嫌われています。
なぜ、テクスティオではそういう悪逆な命令を採用しているのでしょうか。
ジャンプ命令が問題なのは「任意の」場所にジャンプできることが大きいと言えます。
テクスティオの場合は、トップレベルにあるact
要素の先頭にしかジャンプできません。
麺を団子に変えたとでもいえばいいでしょうか、柔軟性は落ちるが絡まることはない、ということが感覚的に理解できると思います。
この制限があるので、ジャンプのないプログラムより、むしろスッキリとして分かりやすいプログラムが書けます。
多くのアドベンチャーゲームでは、ポインタとなる主人公が場面(act)を移動していくというシチュエーションが中心となるので、理解も記述もしやすいという判断です。
HTMLだとハイパーリンクはa
なので、go
ではなくa
にすべきかと思ったんですが、ハイパーリンクのように選択の余地があるのではなく、強制的に移動するので、移動という意味の強いgo
を採用しました。
ただし、移動先の記述には、HTML準拠のhref="ファイル名#アンカーID"
を採用しています。
サブルーチン
act
、p
、select
、option
の要素は、次のようにトップレベルにid属性付きで配置すると、サブルーチンとして呼び出せます。
<!-- 定義 --> <p id="noObject"> 特に何もありません。</p>
そして、id属性付きの空要素を書くことで呼び出しが可能です。
<!-- 呼び出し --> <p id="noObject"/>
つまり、サブルーチンの製作、あるいは呼び出しのための特別な要素はありません。
トップレベルに置かれるとか、内容を持たない空要素であるとかの文脈によって、要素の機能が変わっています。
イメージ的には空要素にid属性をつけることで、ぷくーっと膨らんで、そこに定義内容が展開される、という感じです。
ちなみに、XSLTのサブルーチンは定義と呼び出しとで属性名が異なり、次のように書きます。
<!-- 定義 --> <xsl:template name="識別子"> 定義内容 </xsl:template> <!-- 呼び出し --> <xsl:call-template name="識別子"/>
p
要素の呼び出しにcall-p
要素を作るという手もありますが、p
要素のサブルーチンは必ず内容が必要ですし、逆に呼び出しに内容は必要ありません。
ならば、名前は同じで、空要素かそうでないかで機能を変えたほうがすっきりしますし、覚えるものも少なくて済みます。
サブルーチンには引数が付きものですが、テクスティオには引数渡しが存在しません。
このため、サブルーチン呼び出しというより、定義された部分を呼び出し位置に展開する、プリプロセッサによるマクロ展開的な感覚が近いと言えます。
どうしても引数が必要な場合は、(大域)変数を使って渡すことになります。