プログラム表記の基本 




 
 
単語の分類
 
 

 Mind のプログラムは単語の集まりであるということを第1章で述べたが、その単語を分類したものを下記に示す。右端は記述例である。
図2-1 単語の分類
                            記述例

                  ┌─数値定数    100
        ┌─定数──────┤
        │         └─文字列定数   「こんにちは」
        │
   単語───┤
 (広義の単語)│         ┌─処理単語    表示する
        └─定数以外の単語─┼─変数など    住所
          (狭義の単語) └─特殊単語    長さ  。

 上記に示したように、単に「単語」といった場合、狭義の側(定数でないもの)の単語を指す場合が多い。また、その狭義の単語の中で最も多いのが「処理単語」である。処理単語は、
表示する
ベルを鳴らす
 など、積極的な処理を行う単語である。動詞名が用いられることが多い。
 これに対し、変数の場合は、
住所
売り上げ
 など、名詞として定義されることが多い(注1)。
注1
これら動詞、名詞の使い分けは強制されるものではない。ただ、引用した ときの自然さを考えるとこのような命名になるだろう。


 
 
単語名と分かち書き
 
 

 どこからどこまでを1つの単語とみなすかというのは、日本語ではやっかいな問題である。英語であれば、単語の間が空白やカンマなどで区切られているので機械的な分離が可能であるが、日本語の場合には本格的にやろうとすると、意味解釈(形態素解析)に立ち入ることになってしまう。
 90%の正解なら上出来と評価される機械翻訳の世界と違って、たとえ0.001%でも不確実なことが許されないプログラムの世界では、自然文解析によって単語を切り出そうとするのは無謀な試みといえよう。
 Mind では分かち書きによってこの問題を避けている。
 分かち書きといっても、いわゆる正しい分かち書きを強制するわけではないので安心して欲しい。「Mindの単語と単語の間は空白で区切る」という、ただそれだけのことである。
注2
Mindで言う「単語」は日本語の文法にならえば「文節」にあたるものだが、あえて「単語」と呼ぶことにする。
 どんなに長い単語であっても、くっついていさえいれば、それで1つの単語として認識される。例えば、
赤い色で表示する
は、「赤い色で表示」という1つの単語である。この単語を引用するには、この長い語をそのまま、
「危険です。」を 赤い色で表示する
のように引用しなければならない(注3)。
注3
単語間の平仮名は無視されるので、この場合、「赤色表示する」と書いてもよい。
 もし、
「危険です。」を 赤い色で 表示する
と分離して記述したならば、「赤い色」と「表示」の2つの単語が記述されているとみなされる。コンパイラは、「赤い色」と「赤い色で表示する」との間に類似性を見いだすようなことは絶対になく、まったく違う単語であると解釈する。
 分かち書きするのが面倒…というように考えずに、むしろ、分かち書きのために人間の側も単語認識が明快になること、そして、どのような複雑な長い単語名(複合語やちょっとした短文)でも自由に創造できるという利点がある…と考えて欲しい。
 複合語の例をあげておこう。いずれもMind に備わっている単語である。
Mindで定義済みの単語例

一文字書き込み
五百ミリ秒待つ
日付を得る
リターンキーを待つ
 あとになったが、単語間を分離する能力のある文字(空白など)は次の通りである。
単語区切りに使える文字

TAB    (タブコード)
空白    (半角/全角とも)
, カンマ (半角/全角とも)
、 読点   (半角/全角とも)
 上記に挙げた文字はすべて空白と等価だと思えばよい。半角文字と全角文字を、どちらも同じように受け付けるのはMind の特色である。


 
 
送り仮名
 
 

 送り仮名ということばについて解釈の違いが生ずるといけないので、ここでは「漢字に続くひらがな」という、機械的な認識であると定義することにしよう。
 送り仮名は、単語認識の点ではすべて無視される。例を示そう。
反応し
反応する
反応させる
 上記の3つは等価である。送り仮名はコンパイラ内部では最終的に削除され、「反応」という名称によって検索される。
 いわゆる送り仮名だけでなく、単語内のひらがなも無視される。先にあった、
赤い色で表示する
という記述も、実際には
赤色表示
に圧縮されることになる。
 一見、乱暴なやり方に見えるかも知れないが、実際にMind を使用してみると、この方法が日本語の特質を利用したものであり、これでまったくさし支えないことがわかる。
 送り仮名を無視するのは、これが複合語の間の送り仮名も含めて、記述する人間の個性や、かな漢字変換システムの熟語辞書の個性が出るきわめて不安定な存在であり、単語識別の対象とするのは危険だからである。
 話を戻すが、平仮名からなる単語は、全部削除してしまうと文字がなくなってしまうので、末尾の助詞(と思われるもの)だけを削除し、あとは残すようにしている。
 頭が平仮名で、後半が漢字の単語も特殊扱いとなり、平仮名が残される。例えば、
ご案内する
は「ご案内」で認識されるので、
案内する
とは違うものとして扱われることになる。
 単語内の中点も無視される。次の2つ
トータル・カウント
トータルカウント
は等価である。
 カタカナが出たついでに説明すると、半角カタカナや半角の英字・記号はすべて全角文字と等価であるとみなされる。さらには、小文字英字と大文字英字は同じものとみなされる。例えば、
VIDEO/8
video/8
VIDEO/8
video/8
の四つの単語はすべて等価である。
 なお、半角カタカナの場合、コンピュータの都合上、濁点や半濁点が1 文字と して独立して置かれるが、コンパイラが単語解釈する際には合体されて1 文字の 全角文字となる。
 このようにMind では、半角文字と全角文字、そして小文字と大文字はできる かぎり平等に扱われる。日常社会であっても、単語の意味が、その活字の大きさ によって変化したりしないのと同じことである。
 さて、送り仮名は無視されるということを述べてきたが、これは、単語認識に ついては無視されるという意味であって、送り仮名がまったく意味を持たないわ けではない。
 一部の単語であるが、コンパイラが助詞を見る場合がある。例を挙げよう(送り仮名に注目)。
10から 3 引く       ‥‥(1)
 10から 引く       ‥‥(2)
と記述することもできる。(1)が標準的なのだが、日本人は(2)の記述も多く使用するので、コンパイラのサービスとして、(2)の記述があった場合には、内部で逆転処理し正しく動作するようにしている。
 このほかには、
住所 氏名 年令に 入れる     ‥‥(一括代入)
住所 氏名 年令を クリアする   ‥‥(一括クリア)
 否定形の送り仮名はエラーとなる。
水素と 酸素を 反応させない
 プログラムとして上記のような記述はそもそも無意味なのであるが、万が一記述された場合に、肯定文と同じように動作するのもまずいので、エラー処理を行っている。
 ついでに、Mind のエラーメッセージについて紹介しよう。先のような否定送り仮名のエラーの場合、次のようなものが出力される。
エラー:”させない”のような否定型の送り仮名は使えません。
 対話中であれば、これがただちにコンソールに表示されて、現在の対話入力がキャンセルとなる。コンパイル中であれば、この他の情報とともにインフォメーションファイル(注4)に書き込まれる。
注4
インフォメーションファイルは、コンパイル中に生成される各種メッセー ジ(主にエラーメッセージ)を書き込むファイルである。
 Mind のエラーメッセージは、おおむねこのようなものなので、従来のプログラム言語にありがちな「メッセージの意味が判らない」といったことはないだろう。


 
 
数値定数
 
 

 基本的な数値演算は整数形式(符号付き32ビットでおよそ−21億〜+21億を表現)で通常の計算には支障ないだろう。これより大きな桁や小数は小数形式を用いる。
 整数の定数を表現するために、0 から9 の数字とマイナス符号(−)が使用できる。
 これらは、全角文字/半角文字のどちらで表記してもよい。下記の2 行、
-123       (半角)
−123   (全角)
は等価である。
 小数の定数も表記できる。
注4
本書で言う「小数」とは一般のプログラミング言語で「倍精度浮動小数」と呼ばれるものに相当し、プログラム中では多くの場合 'double' と表記される型である。
 以下は小数定数の表記例である。
3.14
1.23E2
-1.23E-2
−1.23E−2   (全角)
 小数が扱える範囲は仮数部で15桁、指数部が+-308である。
 Mindでは小数データの仮数部の有効桁が整数データのそれより長いので、裏技的ではあるが、小数形式を精度の高い整数演算として使うこともできる。
 その他に、以下の方法で8進数、16進数が記述できる(末尾H以外の形式はMind Version7以降)。
図2-2 10進以外の数値の記述
                      記述例
  8xnnn    8進数     8x644  8x644
  0xnnn   16進数     0xaf64de89
  nnnnH   16進数     6800h  6800H
 0nnnnH   16進数     0af64de89H
  '8xnnn'形式の8の部分(基数)はこのほか2〜16の範囲を指定可能。   下段2つは末尾に'H'(全半大小問わず)を付ける方法で16進を表記    するもの。先頭文字がA〜Fの場合には先頭に0を付ける。

 プログラムを判りやすくするために、数値に助数詞を付けることができる。例えば、
助数詞を付けた例

560を 売り上げに 入れ
生徒名(3、2、5)を 表示し
という場合の「円」「年」「組」がそれに当たり、ソースコードの可読性を高められる。
 助数詞を付けられるとはいっても、Mind では、「数字に続いて数字でないものが現れたら、その部分を無視するという簡単な方法で、助数詞をコメントのように書くことを許容しているだけである。(上記では続く送り仮名も無視される)
 助数詞の意味をコンパイラが解釈しているわけではないので、例えば、
2億円に 100円を 加える       →結果は102 !
などと記述してもコンパイラは何も言わない。単位系の管理はプログラマの責任である。


 
数値定数を単語定義
 
 数値を単語名(シンボル)として定義することもできる。


構文=
<単語名> 定数 <数値>。    ←単なる数値を単語として定義 <単語名> 定数 <Mind式>。  ←式を評価した結果の数値を単語として定義           ─── Mind式に使える演算語 ───           加え、 引く、 掛け、 割る、           AND、 OR、 XOR、           左シフト、 右シフト、           等しい、 異なる、 大きい、 小さい、 以上、 以下
 たとえば、
(例) 最低温度は 定数 250度。
のように定義すれば、以後のプログラム中にこの単語(最低温度)が現れたとき、そこに「250」という数値が書かれているのと同じ扱いを受けるようになる。
 もし、プログラムの中に(最低温度の意味で)「250」という数字がたくさん表記されているような場合、この方法を使えば250という具体的な値の表記を1箇所に集中させることができる。将来、値を変更するような場合に、1箇所を訂正するだけで済むという利点のほか、プログラム中に単に「250」と書かれているよりも、「最低温度」と書かれているほうがプログラムの意図がよく分かるという利点もあるので積極的に利用したい。
 構文説明の後半にある<Mind式>を使った例を以下に示す。
(例1) 最低温度は 定数 250度。 最高温度は 定数 最低温度に 100度を 加えたもの。
 上記2行目では「定数」の右辺で数値の演算(Mind流の演算式)を記述しているが、このような表記も受け付ける。上記例は以下のように定義したのと同じになる。
(例2) 最低温度は 定数 250度。 最高温度は 定数 350度。
 もし、「最低温度は変更することがあるものの、最高温度は常にそれより100度高い」というルールがあるのであれば、変更が1箇所だけで済む例1のほうが優れた定義となる。(最低温度と最高温度の関連性がプログラム中に明記される利点もある)
 また重要なこととして、例1のような表記にすることで実行速度が落ちたり、メモリを余計に消費するようなことはない点が挙げられる。ソースプログラムは多少長くなるものの、ここでの演算はコンパイル時におこなわれるため実行時間やメモリ消費にはまったく影響を与えない。


 
 
文字定数
 
 

 Mind でいう「文字」は文字コードのことを指し、最終的には数値と同じ扱いを受ける(Mindでは「文字」と「文字列」は明確に区別するので注意すること)。
 例えば、半角のAという文字(の文字コード)を表すのに、
65
という、10進数のASCII コード値を(もちろん16進でもよいが)表記することもできるが、これではいかにも判りにくいので、
'A'      ←65と書くのと同じ
というように、シングルクォート記号でその文字を囲むことで、文字コードを表現できるようにしている。この表記を「文字定数」と呼ぶことにする。なおシングルクォートは、半角でも全角でもよい。
 コンパイラは、ソースコード内にこのような表記を見つけると、直ちに65という数値に変換してしまうので、最終的に数値と同じ効果を持つ。(文字コード表を引くのをコンパイラがおこなっているだけ)
 次のようにして漢字の文字定数も記述できる。
'漢'     ←8ABFHと書くのと同じ(Windows環境の場合)
 Mindの内部では数値は32ビット長で処理されることと関係するが、このビット長に収まってさえいれば複数文字の文字コードを定数として記述できる。しかしこれは裏技的使い方なので(文字列のように見えてしまう)乱用しない方がいいだろう。例を示しておく。
'ABC'     ←内部的には 00414243H という値の数値として評価(文字列ではない)
'漢字'    ←内部的には 8ABF8E9AH という値の数値として評価(文字列ではない)

 文字定数は実質的に数値定数と同じであるため、先に説明した数値定数の単語定義(シンボル化)がそままま使える。たとえば以下のような定義方法がある。
(例) 英字を代表する文字は 定数 'A'。 漢字を代表する文字は 定数 '漢'
 標準ライブラリですでに定義されている文字定数は以下の通りである。(標準ライブラリ内での定義内容そのままを記した)
  (代表的な制御コードのシンボル定義) NULは        定数  00H。  (Null) SPCは        定数  20H。  (Space) BELは        定数  07H。  (Bell) BSは         定数  08H。  (Back Space) ESCは        定数  1BH。  (Escape) TABは        定数  09H。  (Tab) CRは         定数  0DH。  (Carriage return) LFは         定数  0AH。  (Line Feed) FFは         定数  0CH。  (Form Feed)   (改行コードや空白文字を日本語名でシンボル定義) 改行コードは      定数 0D0AH。  Windows環境向け 改行コードは      定数 0AH。    Linux環境向け 半角空白は       定数  ' '。 全角空白は       定数  ' '。
 上記下段の日本語名の文字定数について補足する。
 まず「改行コード」(行末コードとも言う)であるが、Mindの標準単語を使っている限り(たとえば「一行表示」によるコンソールの改行)、プログラマは改行コードをほとんど意識しなくて良いようになっているが、場合によっては明に改行コードを扱わなくてはならないこともあるだろう。
 しかし、Windows環境ではCR/LFの2文字、Linux環境ではLF(日本語にEUC-JPを設定している場合)の1文字と、OSによる違いがある。これに対し、「改行コード」という抽象名を使うようにすれば、Mindの走行環境によって自動的に正しい値が選択されるのでプログラマの負担が軽減される。
 Windows環境での「改行コード」は上記のように 0D0AH で定義されている点が特徴である。CRとLFをパックして16ビットにしたものだが、漢字コードの体裁をとっている。このまま、たとえば「一文字表示」あるいは、ファイルへの書き込みであれば「一文字書き込み」を使えば、CRとLFが一度に出力されることになり、OS環境の違いによって2文字を書き込んだり1文字を書き込んだりする面倒さが解消される。
 次に「半角空白」「全角空白」であるが、もしこれを使わずに、空白文字を一文字表示するプログラムを書くと以下のようになる。
    ' 'を 一文字表示する     ' 'を 一文字表示する
 上段は半角空白を1文字表示し、下段は全角空白を1文字表示するものだが、ソースプログラムをよく見ないと違いは分からない。一方、標準ライブラリの文字定数を使えば以下のようになり、
    半角空白を 一文字表示する     全角空白を 一文字表示する
上記であればプログラムの意図が明確になるので積極的に使いたい。(数値定数なので、使ったからといって実行速度が落ちたり、メモリを余計に消費するようなことはない)


 
 
文字列定数
 
 

 文字列定数については、すでに、
「こんにちは。」を 表示する
というような形式で解説に利用してきた。あまりにも日常的な表記なので説明することもないだろう。
 半角カナと全角カナの 「 」 は同じように利用できるが、開きと閉じの半/全は統一する必要がある。
 他のプログラム言語での慣習を考慮し、次のような表記も許している。
"こんにちは。"を 表示する
 上のダブルクォート記号は半角/全角のどちらも使用可能だが、半角の方がよく用いられる(開きと閉じの半/全は統一する必要がある)。ダブルクォートによる文字列定数表記は、その内部に「」自身が含まれるような場合に使えることや、ファイル名を括る場合に 「test.txt」 よりは "test.txt" のほうがなじみがあるかも知れない。
 文字列定数の長さは最大32767 文字(半角換算)までである。
 長い文字列で1 行に収まらない場合には、次のように、定数末尾に「続」を付加することで、次の行に継続できる。結果として長い1つの文字列として処理される。
「これは長い長い長い長い長い長い長い長い長い」    ←次行への継続を表す
「長い長い長い長い長い長い長い文字列です」を 表示する
 文字列の中に改行コードを挿入したい場合には、次のような表記による。
「末尾に改行コードが有ります。&改行&
改行コードを次のようなシンボルとして記述することもできる。
「末尾に改行コードが有ります。&CRLF&
 両者は同じような効果だが多少異なる。前者ではOS環境を考慮した改行コード(具体的には LF または CR+LF のいずれか)を挿入するが、後者はコードの値を明示してしまっているため、他のOS環境では所定の動作と異なってしまうことがある。たとえばLinux環境であれば、改行コードは(Mind標準としては)&LF&とすべきところである。前者のように &改行& としておけばOS環境の違いは考えなくて済む。
 改行コード以外の制御コードとしては以下を使うことができる。
「文の中に&TAB&が有ります。」
「文の中に&ESC&が有ります。」
 前記は制御コードのシンボルを指定したものだが、直接に16進表記を埋め込むこともできる。以下は例である。(他の場面と同様に、16進数は半角/全角、小文字/大文字どちらでも可)
「末尾に改行コードが有ります。&0D0A&」  ←&CRLF&と同じ効果
「文の中に&07&が有ります。」    ←&TAB&と同じ効果
「文の中に&1B&が有ります。」    ←&ESC&と同じ効果


 
文字列定数を単語定義
 
 文字列定数を単語名(シンボル)として定義することもできる。

構文=
<単語名> 文字列定数 <文字列定数>。
 文字列定数を上記のようにしてシンボル化しておくことで、プログラム中に頻繁に現れる同じ文字列を1元管理でき、プログラムのメンテナンスが容易となる。
 以下は例である。
(例) ファイル一覧コマンドは 文字列定数 "dir /w"。 ファイル一覧を表示するとは (・ → ・) ファイル一覧コマンドを プログラム実行し ・・・     ・・・
 なお、文字列定数ではないのだが、あらかじめ決まった文字列を得ることができる‥という意味で類似のものとして、処理単語「指定桁の空白文字列」がある。以下のように呼び出すことで、指定した桁数の空白文字の羅列を文字列として得ることができる。

構文=
<桁数>の 指定桁の空白文字列 → <文字列>        注:最大200桁まで利用可能。0桁なら空列が返される。           200桁を超える値を指定しても200桁しか返さない。
 たとえば以下の2行のプログラムは等価である。
(例)     " "を 表示し     10桁の 指定桁の空白文字列を 表示し
どちらが、よりプログラムの意図を表しているか言うまでもないだろう。


 
 
コメント(注釈)
 
 

 Mindではコメントは次の2通りの方法によって記述できる。次の2行とも行後半に書かれているものはコメントである。
                   ( )内はコメント扱い
「こんにちは。」を 表示すること。   (これは暫定的な表示)
「こんにちは。」を 表示すること。   ※これは暫定的な表示
                   '※'から行末までコメント
 前者では'('から')'までがコメント扱いとなる。後者では'※'記号から行末までがコメント扱いとなる。
 Mindのプログラムはスタック経由でデータを渡すため、処理単語のスタック仕様はとても重要となる。次のソースコードはMindのプログラムでよく見かけるものだが、処理単語を定義するとき、ついでにスタック仕様も書いている。
処理単語を定義するときスタック仕様をコメントする

売り上げ計上とは (金額 → ・)
    ・・・・・・
 上で (金額 → ・) の表記により、この処理単語は金額をあらわすデータを1つ受け取り、戻るときはスタックは空で帰る‥と言うことか分かる。ここはコメントなのでプログラムの動作としては意味が無いのだが、その処理単語を使う上での重要な情報となるので、なるべく書くようにしたい。
 細かなことになるが、かっこ記号はコメントだけでなく、配列の添え字や、数式中の優先指示にも使用されるので注意したい。かっこがコメントとして成立するためには、次のように両端が空いている必要がある。
ソース行途中のコメント

2で (2=諧調) イメージ処理すること
  ↑空ける  ↑空ける
 なお、以下はコメントのための機能ではないが、コメントが多くの行にわたる場合、この方法も利用できる。
コンパイル抑止。
−−−−−−−−−−−−−−−−−−−−−−−−
−−−−−−−−任意のコメント−−−−−−−−−
−−−−−−−−−−−−−−−−−−−−−−−−
コンパイル抑止終り。
上記の2つの単語は、コンパイラに指示を与える特殊な単語である。この2つに挟 まれた部分はコメントと同じで無視される。各行について()を付けたり、※記号 を付けたりする必要がないので、長いコメントでは便利な方法である。


 
 
処理単語
 
 

 本章の冒頭でも解説したように、Mindのプログラムは単語の羅列である。単語の種類としては変数、定数、処理単語などがあるが、本セクションでは処理単語について解説する。

 プログラムを自動車に例えれば、単語は自動車の部品に相当する。最初にボルトやナットのようなものを組み合わせて小さな部品を作り、それをさらに組み合わせて大きな部品を作る...というように組み合わせるのが普通である。Mindのプログラムもこれとまったく同じである。
 単語の定義は次のような記述による。
  [1] ・・・・・とは            ←注:「とは」は「」でもよい     ・・・・・・・・・・・・・・・・・     ・・・・・・・・・・・・・・・・・     ・・・・・・・・・・・・・・・・・である。             [2]
 上記のように非常に簡単なものである。この例では[1]の「......とは」の末尾でいったん改行しており、また、[2]のブロックを字下げ(少し右寄せ)しているが、見易くするためにこうしただけで、強制されるものではない(ただ、慣習としてこの形式で書くことが多い)。
 [1]は新しく定義する単語名を記述する。どのような名称を付けてもよいが、すでに定義されている名前や、文字列定数や数値定数となるようなものは命名できない。送り仮名の「とは」あるいは「は」は必須である。
 [2]はこの単語の定義内容となるものである。定義の最後は必ず「。」で終わる必要がある。上図では「。」のところを、「である。」としているが、それらしくするための飾りであり、意味はない。気分としてはこのようなものであると理解されたい。
 アセンブラやC言語などの経験者は、短い単語や略号を命名しがちであるが、Mindでは逆に長くてもいいから、その動作を理解しやすい単語を命名するのがよいこととされる。
 単語の長さはとくに制限はない。また、名前が長いからといって、プログラムサイズが大きくなったり、実行速度が落ちたりするようなことはない。ただソースコードが大きくなるだけのことである。
 つぎの定義例をご覧頂きたい。
目をかくとは     ・・・・・し     ・・・・・すること。 鼻をかくとは     ・・・・・し     ・・・・・すること。 口をかくとは     ・・・・・し     ・・・・・すること。 顔をかくとは     目をかき     鼻をかき     口をかくことである。
 「目をかく」「鼻をかく」といった単語が小さな部品に相当する。そして、これらを次々と実行する大きな部品が「顔をかく」である。そしてたぶん、この「顔をかく」は、さらに上位の単語で引用されることになるだろう。
 この一連の定義で重要なのは、下位の単語(小さな部品)から先に定義するという点である。言葉を換えると、定義内容として引用する単語群はすべて定義済みでなくてはならない、という意味にもなる。
 上記例でいえば、「顔をかくとは…」という定義を、目や鼻の定義に先立って記述することはできない。
 先に自動車の構造の話をしたが、あれと同じことで、小さな部品が完成していなくてはそれを組み合わせた大きな部品は作ることができないという、常識的な理由による。
 さて、ユーザーが定義する単語のうち、「メイン」という単語は特別な扱いを受ける。
○○とは     ・・・・・し     ・・・・・すること。 △△とは     ・・・・・し     ・・・・・すること。 メインとは     ○○し     △△すること。
 上のように、ユーザープログラムの最後は「メイン」という処理単語の定義で終わるのが普通である。
 コンパイラは「メイン」という単語を見つけると、これがプログラムの最高レベルの単語であると理解し、プログラムが起動したときに、この単語から処理を開始するように処置する。
 「メイン」がプログラムの最後に定義されることは重要である。この位置であれば、プログラム内のすべての単語をこの位置から引用できる。
 ちなみに、最も短いプログラムは次のように、たった1行で記述できる。
メインとは。
 上の場合、定義内容が存在しないので、プログラムとして起動しても何もせずに終了することになる(「メイン」がないプログラムを起動した場合も同様である)。
 プログラムの中に意図的に「メイン」を置かない場合もある。作成するプログラムが、ライブラリとして機能する場合である。つまり、さらに上位のモジュールが存在する場合で、「メイン」はその上位モジュールで定義されることになる。


 
局所処理単語
 
  このセクションは上級者向けなので初級者は読み飛ばして構わない
 処理単語の定義の内部に小さな処理単語を定義できる。親となる処理単語のためだけの下位処理(子の処理)を定義する時に利用する。
 親・子関係が視覚的に理解しやすいことのほか、局所処理単語はその親以外からは「見えない」ため、子の処理を(関係のない)外部から隠蔽する働きもありプログラムがより強固になる。
 また、親から見て下位となる子の処理単語を普通に「外」で定義することに比べると、子から親の局所変数を自由にアクセスできるメリットもある。

構文=
処理1とは       ( ○○は  変数 )  ←局所変数群(もし有れば)       ( ○○は  変数 )  下位処理1とは        ←局所処理単語     ・・・・・・・・  下位処理2とは        ←局所処理単語     ・・・・・・・・  本体とは           ←本来の親の単語定義はここから     ・・・・・・・・     ・・・・・・・・すること。
 局所処理単語を含めた処理単語定義の例を上に示した。この例では「局所処理1」「局所処理2」という2 つの単語が局所処理単語である。次のような注意がある。

 
処理単語の属性を指定する
 
  このセクションは上級者向けなので初級者は読み飛ばして構わない

 今まで例に書いた処理単語の定義では、受け取るデータの数やその型、返すデータの型、などは明示しなかった。
 「Mindの文法検査は限りなくゆるい」のが流儀なので通常はそれで構わないのだが、本機能を使うことで明に型を指示することもできる。


構文=
<処理単語名>とは 処理単語 <属性> <属性> ・・ <属性>     ・・・・・し        ↑下線部は途中で改行してはならない     ・・・・・すること。           ─── 属性に記述できる語 ───           整数入力、 小数入力 | 整数出力、 小数出力           逆転抑制            (その他細かなものについては上級編に)
 以下は例である。
(例1) 差を表示とは (数値1、数値2 → ・)     引いたものを、「差は 」を 表示してから 数値表示し 「 です。」を 一行表示すること。
(例2) 差を表示とは (数値1、数値2 → ・) 処理単語 整数入力 整数入力     引いたものを、「差は 」を 表示してから 数値表示し 「 です。」を 一行表示すること。
 上の2つは動作としてはまったく同じだが、この処理単語を引用する際、後者は簡単なデータ型の検査が行われるようになる。
 たとえば引用例としては次のような表記が考えられるが、
(正しい呼び出し) ○○とは         今回の成績は 変数         前回の成績は 変数     ・・・・・・     今回の成績と 前回の成績の 差を表示し     ・・・・・・
 「差を表示」の定義が例2のようになっている場合で、もし「今回の値」または「前回の値」が下記のような小数だった場合、コンパイル時にエラーとして検出することができる。
(誤った呼び出し) ○○とは         今回の成績は 小数変数         前回の成績は 小数変数     ・・・・・・     今回の成績と 前回の成績の 差を表示し     ・・・・・・               このようなエラーとなる↓            処理単語"差を表示"に与えるデータの型が誤りです。
 前記「構文=」に記している「属性に記述できる語」について説明する。
 入力データ型を明示する語として、
    整数入力
    小数入力
の2つが使える。これらが何も書かれていない場合は入力データ型の検査は行われない。(検査サービスが行われないというだけであり、処理は正常に行われる)。
 先の「例2」では、「整数入力 整数入力」と、同じ語を2つ続けて書いていることに注目して欲しい。この場合は、スタックから整数値を2つ受け取ることを意味する。これによって定義された処理単語「差を表示」が引用された場合で、かつ、入力データがその処理単語の直近に書いてある場合に検査が行われる。2つ受け取る予定の処理単語であっても、その引用時に1つしかデータが書かれていない場合、エラーにはならず、その1つのデータが検査される。
 入力型の属性の有り無しで整理すると以下のような場合分けになる。
    (記述無し)         ←入力データ無しとみなされる
    ○○入力          ←入力データが1つとみなされる
    ○○入力 ○○入力     ←入力データが2つとみなされる (注:2つの入力型は同じであること)


 
 
関数
 
 

 一般的なプログラム言語と同じような「関数」も定義できる。基本的には内部動作は通常の処理単語と同じで、コンパイラによる属性の認識と、上位から呼び出す際の表記が主な違いである。
 以下が定義ルールである。


構文=
<関数名>とは 関数 <入力データ型> ・・ <入力データ型> <出力データ型>     ・・・・・し          ↑下線部は途中で改行してはならない     ・・・・・すること。         注:「関数」から末尾の<出力データ型>までを1行内に表記すること         注:「入力データ型」は1個〜3個を書く。この個数が関数の引数個数となる         注:「入力データ型」が複数ある場合、すべて同一型であること         注:「入力データ型」が書かれない場合は1つの整数入力とみなされる         注:「出力データ型」が書かれない場合は整数出力とみなされる           ─── データ型に記述できる語 ───           整数入力、 小数入力 | 整数出力、 小数出力
 上の構文は前項「処理単語の属性を指定する」(○○は 処理単語 ・・・・・)のそれと似ているが、属性が省略された場合の扱いが異なる。関数では<入力データ型>が省略されると1つの整数を引数とすると解釈され、<出力データ型>を省略すると整数を結果として返すものとされる。
 たとえば以下の2例は定義の効果として同じである。
(例a)      ↓入力データ型も出力データ型も書かれていない場合は・・・、 下限制限とは 関数     複写したものが 10より 小さい         ならば 捨て             10をつむこと         つぎに。
(例b)      ↓このように書いたものと同じになる 下限制限とは 関数 整数入力 整数出力     複写したものが 10より 小さい         ならば 捨て             10をつむこと         つぎに。

 
関数の引数
 
 たとえば前記の関数「下限制限」は以下のように呼び出すことになる。
    下限制限(入力値)に 1000を 掛け ・・し
 あるいは、以下のように数式表現中で呼び出すこともできる。
    [下限制限(入力値) * 1000]を ・・し
 また、引数に数式(数式表現)を書くこともできる。以下は例である。
    下限制限(入力値 + 3)
注5
関数の引数に数式を使った場合、本来の数式表現とは異なり、括弧による演算優先表記はできない。
 数式表現については、第6章「数値演算」の中の「数式表現」を参考にされたい。
 逆に、引数の中で複数の語をMind流の計算式として書くことはできない。
(誤り)     下限制限(入力値に 3を 加え)
 2引数や3引数の関数を呼び出す場合、一般的なプログラム言語のように半角カンマ(,)がそれらの区切りに使えるのはもちろんだが、空白や読点(、)でも構わない。たとえば以下は同じである。
    二値の平均(下限,上限)を ・・し    ←半角カンマ(,)を使う
    二値の平均(下限,上限)を ・・し   ←全角カンマ(,)を使う
    二値の平均(下限、上限)を ・・し   ←読点(、)を使う
    二値の平均(下限 上限)を ・・し   ←空白を使う(半角でも全角でも可)

 
等価な関数 を使った定義
 
 既存の処理単語がある場合、その処理単語の属性のみを変更し処理内容はそのまま流用する‥ような、特殊な関数定義ができる。次のように定義する。


構文=
↓新関数  ↓既存処理単語 ○○は   △△と 等価な関数。   ←処理単語「△△」を1引数の新関数「○○」として定義 ○○は   △△と 等価な関数2。  ←処理単語「△△」を2引数の新関数「○○」として定義 ○○は   △△と 等価な関数3。  ←処理単語「△△」を3引数の新関数「○○」として定義
 実は、たとえば、
○○は   関数     △△すること。
とすれば同じことは出来るのだが、等価な関数を使ったほうがオブジェクトコード生成量や実行速度の点で有利である。
 ちなみに、標準の関数「ABS」「MAX」などいくつかは本機能を使って次のように定義されたものである。
ABSは 絶対値と  等価な関数。 MAXは 大きい方と 等価な関数2。
 上記によると、たとえば「MAX」と「大きい方」は機能としては同じだが、呼び出し方法が異なる2語ということになる。(ベースとなるのは「大きい方」である)
(利用例) MAX(値1、値2)を ・・・ 値1と 値2の 大きい方をとり ・・・

 
関数の処理単語風呼び出し
 
 直前に解説した関数「MAX」であるが、実は次のように二通りの表記ができる。
(利用例) MAX(値1、値2)を ・・・ 値1と 値2の MAXをとり ・・・
 このように、関数は通常の処理単語風の記述により呼び出すことも可能である。(裏技的ではあるが)
 なお逆に、通常の処理単語を関数風に呼び出すことはできない。


 
 
等価定義
 
 

 ある単語に別の名前を付ける機能である。

構文=
<新名称>は <旧名称>と 等価。
 以下は標準のfileライブラリ内部で実際に宣言されているものだが、他人に使ってもらうライブラリの作成などでは、このような定義を積極的に使うことを勧める。
タイムオーバー?とは タイムアウト?と  等価。 タイムオーバ?とは  タイムアウト?と  等価。  注:日本語で「タイムオーバー」は「タイムアウト」と同じ意味で使われることが     多いので、どちらを書いても良いように等価語を定義している。     また「タイムオーバ」は「タイムオーバー」の末尾音引きを省いた表記だが、     これも同様に等価定義している。