Mindで扱うことのできるデータの種類は下記のようなものである(注1)。
図4-1 データの種類
┌─整数
|
┌─数値────┼─倍精度整数 (本書では解説しない)
│ |
│ └─小数
データ──┤
│
│
└─文字列
- 注1
- このほかにも、これらのデータの集合をデータとして扱う構造体や型紙というものもある。
PascalやCなどの言語と異なり、Mindではデータをスタックに置く関係上、データ型と変数の型は1対1には対応しない。例えば、整数のデータ型は1つしかないが、それを格納する変数の方は3種類存在する。
とりあえずおおざっぱに、「Mindのデータには数値と文字列の2種類がある」 と単純に考えることにしよう。
数値データと文字列データは次元が違うことに注意しなければならない。例えば、数値データと文字列データを比較することは無意味である。
なお、データはスタックに置かれてしまうと、それが数値なのか文字列なのかは、もはや識別不可能となる。したがって、プログラムの組みかたによっては、「文字列に10を掛けたり」あるいは「数値と文字列を比較する」ようなことをやってもエラーにならない場合もあるので注意したい。
Mindでは変数は必ず定義してから使用する。
数値を格納するための変数には大きく分けて整数変数と小数変数があり、定義は次のように行う。
構文=
○○は 変数。 (32ビット整数変数)
○○は 小数変数。 (64ビット小数(浮動小数)変数) (注2)
上記で「○○」が変数名となる。定義の最後には「。」が必要である。
整数変数のバリエーションとして以下のような定義もある
構文=
○○は ワード変数。 (16ビット整数変数)
○○は バイト変数。 ( 8ビット整数変数)
- 注3
- 「ワード変数」は文字データを格納するのに向く。
- 「バイト変数」は配列・構造体・型紙の中でのみ使用可能。
- これらの変数に負の値は格納できない。
「ワード変数」と「バイト変数」は、格納するデータが明らかに短いビット数以下に収まることが分かっている場合に、データ領域の消費を少なくする目的で使用される。
大は小を兼ねるで、これらを用いないで常に「○○は変数」を使っても何ら支障はない。初心者はこれらの変数については当面、その存在だけを知っていればよいだろう。
次は数値変数の定義例である。
売り上げは 変数。
この定義のあとで「売り上げ」と引用すれば、この変数の内容が参照される。次がその例である
売り上げが 10000円より 大きい ならば ・・・
売り上げを 数値表示し ・・・
変数に値を代入したり、更新する場合には次のような単語を使用する
売り上げを クリアする
100円を 売り上げに 入れる
100円だけ 売り上げを 増加する
(上のような、変数に副作用を及ぼす処理単語については、改めて第6章で解説する)
「増加」の使用例を示そう。
〔プログラムA〕
売り上げは 変数。
売り上げ計上とは (金額 → ・)
売り上げを 増加し
「毎度ありがとうございます」を 表示し 改行すること。
上のプログラムは、「100円を 売り上げ計上する」というように引用する。この単語中で「増加」という単語を使っているが、そこには増加金額は記述されていない。金額をスタック渡しにしたからである。
また、上記のプログラムには次の赤字で示す記述がある。
売り上げ計上とは (金額 → ・)
・・・・・・
かっこを使ったコメントであるが、このスタイルは「スタック仕様」と呼び、この単語が実行される時のスタックの 実行前 と 実行後 の様子を表したものである。ここで「・」は実行後のスタックが空であることを示す。
この場合のスタック仕様は、「スタックから金額を受け取り、空になって戻る」ことを表している。
コメントだから、これを書かないとプログラムとして動かないというものではないが、これは簡単ながら処理単語の使い方の説明になっており、メンテナンスのためにも記述することを強く勧める。どんな単語でも、その単語名とこのスタック仕様(同じ行に書かれる)を見れば、大体の見当がつく。
店に態度の悪い店員がいて、高い買い物をした客にだけ「毎度ありがとうございます」をいう......というケースをプログラムで示そう。
〔プログラムB〕
売り上げは 変数。 ←大域変数
売り上げ計上とは (金額 → ・)
金額は 変数 ←局所変数
金額に 入れ
金額だけ 売り上げを 増加し
金額が 1000円 以上
ならば 「毎度ありがとうございます」を 表示し 改行する
つぎに。
上図で初めて「局所変数」が使用されている(赤字の部分)。
局所変数は、処理単語の定義に入った最初のところで定義され、その単語を実行している間だけ使用できる変数である。単語の実行が終わったとき(つまり「。」に到達したとき)には、この変数はきれいに消滅し、名前も忘れてしまう。
一方、いままで解説してきた普通の変数は、この局所変数に対して「大域変数」と呼ばれ、プログラムの起動から終了までの間、ずっと存在している。
さて、プログラムBではAに比べて少しスタイルが変更になった。このように変わったのはスタックの使い方が関係している。
プログラムAの場合には、スタックで渡された金額を、直接に変数の増加分として使用できた。そのため、処理内容はいきなり「売り上げを増加し」で始まっていた。
ところがBでは、渡された金額を2つの用途に使用しなくてはならない。1つは売り上げの増加用として、もう1つはお礼をいうかどうかの判定に用いるためにである。
もしBでも、Aと同じように、「売り上げを増加し」から始めたのでは、その時点でスタック上の金額データが消滅してしまい、金額が分からなくなってしまう。つまり、お礼をいうかどうかの判定ができない。
そこで、Bでは「金額」という局所変数を設け、スタックから受け取った金額をいったんここに格納するようにした。
変数に格納したデータは、スタック上のデータと違って、何度でも参照してよい(消えるようなことはない)。
プログラムBのように、少しの間だけ内部処理として利用する変数は、大域変数とせずに、このような局所変数として宣言する習慣をつけたい。局所変数の使用は次のような利点をもたらす。
- データ領域の節約になる(この単語の実行時に領域が確保され、実行が終わると解放される)
- 見た目でこの処理単語だけが利用する変数であることが明確になる(メンテナンス上、優れている)
- 処理単語の定義の終りで、その中で宣言された局所変数をシンボルテーブルから抹消するので、このあとでまた同じ変数名が使用できる(シンボルの衝突の心配が減る)
大域変数では、
○○は 変数。
↑
のように末尾に「。」を付ける必要があったが、局所変数は逆で、
構文=
○○とは
△△は 変数 ←局所変数
△△は 変数 ←局所変数
・・・・・・・・・・・・
・・・・・・・・・・・・。
のように、変数宣言に「。」を付けない。もし付けると処理単語全体の定義の終りであるとみなされてしまうので注意する。
また記述スタイルの観点として、局所変数の宣言はこれに続く処理単語の定義文と区別がつくように、字下げをする(定義内容よりもさらに右に寄せる)ことを勧める。
さて、プログラムBをさらに変形してみよう。Bでは、売り上げ金額が与えられたが、そうではなくて、商品の単価と個数が与えられる......という仕様にしてみる。
〔プログラムC〕
売り上げは 変数。
売り上げ計上とは (単価、個数 → ・)
単価は 変数
個数は 変数
金額は 変数
単価と 個数に 入れ
単価と 個数を 掛け 金額に 入れ
金額だけ 売り上げを 増加し
金額が 1000円 以上
ならば 「毎度ありがとうございます」を 表示し 改行する
つぎに。
この単語は、例えば、
120円が 5個で 売り上げ計上する
というように引用されることになる。
さて上記プログラムではもう1つ新しい表記が使われている。次の部分である。
単価と 個数に 入れ
上のような記述はスタックから渡された 複数のデータ を 複数の変数 に一括して代入する操作である。必ず、
規則=
......と ......と ......に 入れる
という助詞が強制される。複数の変数を「と」で連結していき、最後の変数のところで、「に」(または「へ」)によって締めくくることになる(注4)。
これは規則とはいっても、我々がふだん使っている助詞の感覚なので難しくないだろう。
注4−1
いかなる場合も、変数への副作用を起こす場合には、副作用を受ける変数に特定の助詞をふることが強制される。複数変数への一括代入では、その最後の変数に特定助詞をふる。
注4−2
複数変数の一括処理ができるのは、次の処理単語に限られる。
「入れる」「クリア」「一つ増加」「一つ減少」
スタックを図示し動作を確認しておきたい。
少し前で処理単語「売り上げ計上」の呼び出し例として、「120円が 5個で 売り上げ計上する」 という例を示した。そのうち、「120円が 5個で」 までを実行したとき、スタックの内容は次のようになっているだろう。
120
5
上記のような状態で、「売り上げ計上する」という単語の実行が始まる。まず、局所変数を定義しているので、次のような局所変数群が確保される。
売り上げ計上とは (単価、個数 → ・)
↓局所変数群
単価は 変数 ←処理単語の呼び出し時に動的に確保される
個数は 変数 ←同上
〜略〜
局所変数の領域は処理単語が呼び出された時に動的に確保される。また初期値は不定なので、明に値を設定した後に参照する必要がある。
処理単語「売り上げ計上」が呼び出された直後、以下の部分が実行される。
単価と 個数に 入れ
上記で何を入れるかといえば、先にスタックに置いた「120」と「5」である。この2つのデータが一度にスタックから取り出され、一気に変数に代入される。代入の結果、スタック内容と局所変数は次のようになる。
(実行前のスタック)
120
5
(実行するプログラム箇所)
単価と 個数に 入れ
(実行後のスタック)
(空)
(実行後の局所変数)
売り上げ計上とは (単価、個数 → ・)
単価は 変数 ←値は 120 になる
個数は 変数 ←値は 5 になる
〜略〜
スタック上のデータの並びと同じ順序で変数に代入されることに注目しよう。もしこの代入を、個々の変数について行おうとすると、
個数に 入れ 単価に 入れ
というように、変数の順序を逆に記述することになり、かなり紛らわしいプログラムになってしまう。(注5)
注5
実際の内部処理としては、まさにこの逆順による個別代入が行われている。スタックの構造上、奥の方にあるデータを先に取り出すことができないためである。
さて、プログラムCをもう一度見てみよう。
〔プログラムC〕 (再掲)
売り上げは 変数。
売り上げ計上とは (単価、個数 → ・)
単価は 変数
個数は 変数
金額は 変数
単価と 個数に 入れ
単価と 個数を 掛け 金額に 入れ
金額だけ 売り上げを 増加し
金額が 1000円 以上
ならば 「毎度ありがとうございます」を 表示し 改行する
つぎに。
Cの方法は、与えられたデータをとにかく局所変数に置いてしまい、その後に演算をする...という方針になっている。
間違いではないのだが、少し冗長である。というのも、スタックから与えられる単価と個数は、もっぱら、この2つの値を掛け合わせて金額を求めることだけに使われるのだから、何も局所変数に代入して記憶するほどのことではない。
次が改良版となる。
〔プログラムC2〕
売り上げは 変数。
売り上げ計上とは (単価、個数 → ・)
金額は 変数
掛けたものを 金額に 入れ
金額だけ 売り上げを 増加し
金額が 1000円 以上
ならば 「毎度ありがとうございます」を 表示し 改行する
つぎに。
上記では、いきなり「掛け」を記述することで、与えられた2つのデータから直ちに金額(=単価×個数)を求め、その結果を局所変数「金額」へ代入している。
Cは冗長で、C2の方が良いといったが、仕様によっては、Cの型を使わざるを得ないこともある。例えば、「計算結果として、単価・個数・金額をに表示せよ」という仕様になった場合である。
入力データである単価と個数をいきなり掛けてしまったら、あとで表示するときに困るので、やはり局所変数の世話になることになる。次にプログラムを示す。
〔プログラムD〕
売り上げは 変数。
売り上げ計上とは (単価、個数 → ・)
単価は 変数
個数は 変数
金額は 変数
単価と 個数に 入れ
単価と 個数を 掛け 金額に 入れ
「単価:」を 表示し 単価を 数値表示し
「 個数:」を 表示し 個数を 数値表示し
「 金額:」を 表示し 金額を 数値表示し 改行し
金額だけ 売り上げを 増加し
金額が 1000円 以上
ならば 「毎度ありがとうございます」を 表示し 改行する
つぎに。
メインとは (・ → ・)
120円が 10個で 売り上げ計上すること。
上のプログラムを実行した例を次に示す。
単価:120 個数:10 金額:1200
毎度ありがとうございます。
文字列を格納する変数を「文字列変数」という。文字列変数は2種類あり、下のように定義する。
構文=
○○は 文字列実体 長さ △△。 ‥‥‥‥��
↑文字列の実体を格納する変数
○○は 文字列。 ‥‥‥‥��
↑文字列の情報(アドレスとサイズ)を格納する変数
まず上の
�� の”文字列実体”は文字通り、文字列の実体を格納するタイプであり、
�� は ”文字列情報”と呼ぶ情報だけを格納する変数である。用途によって使い分ける。
文字列実体の変数
まず、普通の文字列実体型の変数について解説する。次に例を示す。
構文=
上の宣言により、「住所」という名前の変数が1つ定義される。
文字列実体変数は文字通り、文字列の実体を格納する容器である。文字列実体変数はその容量に注意を払う必要がある。上の例にある「長さ 100桁」は100バイトの容量を指定したことになる。ちなみに助数詞の「桁」は気分として書いたものであり、もちろん「バイト」でもいいし、助数詞を書かなくてもいい。
長さの単位はバイト数なので上記例はASCII文字であれば100文字を、すべて日本語なら50文字を格納できることになる。(注6、注7)
注6
旧版のMindとの互換性のため、長さ指定を省略する記法も許されている。長さを指定しない場合、80バイトがとられるが、できるだけ指定するようにしたい。
注7
変数の容量を超える文字列を格納しようとした(代入しようとした)場合、はみ出た部分は捨てられる。メモリ域をオーバーして書き込むような不都合は起こらない。
たとえば残量が1バイトのとき、その最後の1バイトに全角文字の半カケラを書き込むことはしない。(1バイト残して代入が終わる)
つまり、文字列実体変数への代入はいかなる場合も安全に行われる。
さて、このようにして定義された変数への代入は、数値変数の場合と同じように、「入れる」によって行うことができる。
「東京都港区青山」を 住所に 入れる ‥‥‥‥��
「住所を入力してください:」を 表示し ‥‥‥‥��
文字列入力したものを 住所に 入れる
�,歪蠖瑤箸靴討諒源�列を代入する例であり、 �△呂△觸萢�の結果として得られる文字列を代入する例である。
文字列変数をクリアするには「クリア」が使用できる。
住所を クリアする
文字列変数のクリアは次の操作と効果としては同じである。
「」を 住所に 入れる
つまり、長さゼロの文字列を代入することが文字列変数のクリアに相当する。
前記 �� のプログラム例であれば、「文字列入力」に入ったとき、オペレータが単にエンターキーを打鍵した場合がこれに相当する。このような、長さゼロの文字列のことをMindでは「空列」と呼び、文字列データの特殊な状態を表すのによく使用されるので覚えておきたい。
文字列情報について
前項のプログラム例として次のようなものがあった(再び同じものを示す)。
「住所を入力してください:」を 表示し ‥‥‥‥��
文字列入力したものを 住所に 入れる
上のプログラム内に「文字列入力」という単語がある。これは文字通り、コンソール(キーボード)から文字列を入力する機能である。
この単語が実行されると、コンピュータはキー入力待ちとなっていったん停止し、オペレーターのキー入力を待つ。この状態でいくつかの文字(文字列)を入力し、最後にエンターキーを打鍵すると「文字列入力」の処理が終了して戻ってくる。
このとき、スタックには「文字列情報」と呼ぶ形式の文字列のデータが置かれている(下図)。
(文字列情報)
このあたりを詳しく解説すると、処理単語である「文字列入力」は、キー入力した文字列を、ライブラリ内部に確保している「入力文字列」という名の文字列実体変数に格納し、そこを指すような情報だけをスタックに置いてリターンするようになっている。
「文字列入力」した文字列が返されるまで
( キーボードから 「横浜市中区」 と入力したと仮定 )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
文字列実体変数: ”入力文字列”
←エンターキー打鍵で「横浜市中区」が格納される
↑�ヽ頁次 �
| ↓�∋仮�
処理単語: 文字列入力
| ↑標準ライブラリ
−−−−−−−−−−−|−−−−−−−−−−−−−−−−−−−−−−
| ↓アプリケーション
↓��処理単語が返す値(=アドレスと長さの合成値)
スタック:
横浜市中区
文字列のデータは不定長で、かつ、大きいために、スタックのような比較的小容量の格納場所にそのまま置くのには向かない。そこで考案されたのが文字列情報である。
文字列情報は、文字列の実体が置かれている(多くは文字列実体型の変数の)メモリアドレスと、その文字列の長さという2つの情報を合成したものである。
文字列データは、実際に利用されるとき、その存在するアドレスと長さの情報さえ伝われば、文字列に関するほとんどの操作を行うことができる...という性質を利用したものである。
我々のに日常でも同じようなことが行われている。例えば、多額のお金のやりとりは現金ではなく小切手を使うとか、不動産(持ち運びができない)を売買するのに現物ではなく証書を使う‥というようなことに相当する。Mindの文字列データというのは、この証書のようなものであると思えばよい。
Mindの処理単語で「文字列を渡す」とか「文字列を返す」などといった場合、それは実際には、文字列の実体を渡したり返したりしているのではなく、文字列情報を扱っている。
文字列の操作を文字列情報の上で実現するこの方法は、文字列の操作のための新たなデータ消費がないことと、実行速度が格段に早いという大きな利点がある。
文字列情報を格納する変数
文字列の変数の型には文字列実体型のほか、もう1種類、文字列情報型の変数が存在する。次のように宣言する。
構文=
局所変数としても定義できる。次のようになる。
構文=
○○とは
住所は 文字列
氏名は 文字列
・・・・・・・・・・・・
・・・・・・・・・・・・。
前項で、スタックに置かれる文字列データは、実は文字列情報であるということを述べたが、文字列情報型変数とは、まさに、この文字列情報を格納するための変数である。
「山田太郎」を 氏名に 入れる
上記のプログラムによって、スタックに置かれている文字列データが文字列情報変数に格納される様子を以下に示す。
文字列データが文字列情報変数に格納される様子
( 実行前のスタック )
(空)
( 「山田太郎」を … の実行後のスタック )
↓正確には、「山田太郎」を指す情報
山田太郎
( 氏名に 入れる … の実行後のスタック )
(空)
( 実行後の変数 )
文字列情報変数:”氏名” ←実体「山田太郎」を指す情報が格納された
文字列情報型の変数は局所変数で多く用いられる。例を示そう。
[A]
挨拶とは (名前 → ・)
名前は 文字列
名前に 入れ
「こんにちは、」を 表示し 名前を 表示し
「さん。」を 表示すること。
上に示した「挨拶」という処理単語は、
「花子」で 挨拶する
のように用いる。画面には次のような応答が現れるだろう。
こんにちは、花子さん。
「挨拶」という単語は、名前をスタック経由で渡されてから実行が始まるようになっている。この単語の内部でまず文字列データを「名前」という局所変数に代入しておき、少したってから、「名前を表示し」というように引用している。
さて[A]のプログラムは、仮置きとしての局所変数を文字列実体型にすれば以下のようにも書ける。
[B]
挨拶とは (名前 → ・)
名前は 文字列実体 長さ 40桁
名前に 入れ
「こんにちは、」を 表示し 名前を 表示し
「さん。」を 表示すること。
AとBはほとんど同じプログラムだが、Aが「○○は 文字列」であるのに比べ、Bは「○○は 文字列実体」と、文字列実体型の変数を宣言している。
両者は動作は同じだが、Bのように仮置き場としての用途に文字列実体型の変数を使うのはメモリ消費・実行速度の両面でコストが高い。さらに後者では変数の長さ宣言も必要であり、「最大でどのぐらい長い文字列が渡されるのか?」と余計な心配をしなくてはならない(文字列情報型は情報を格納するだけなので長さの心配は無い)。このようなケースでは前者(文字列情報型)を使いたい。
なお、1つ前のAのプログラムは下記のように簡単にすることもできる。
[C]
挨拶とは (名前 → ・)
「こんにちは、」を 表示してから 表示し
「さん。」を 表示すること。
上記で2つ目の「表示」は、一見すると何を表示するのか‥が不明であるが、しかしながら日本語として通用するように見えるのと同様、これで正しく動作する。すなわち、スタックから渡された文字列をすぐに使わずに、「こんにちは」を表示したあと、単に「表示し」とやることで、仮置き場を経由せずに直接に利用(消費)している。スタックの特質を積極的に利用したケースといえるだろう。
Cではプログラムが短くはなったが、若干読みづらい点もあるので、慣れてくればこのような書き方もある‥という程度に考えておこう。
さて、本当に変数を使わなくてはならない場合を示す。先のプログラムを少し変形するために次のような仕様を追加してみよう。
- 親しい人なら「やあ、」、そうでないなら、「こんにちは、」で始まるようにする
親しい人なら...というところが難しそうなので、ここでは「親しい人?」という処理単語がすでに定義済みであると仮定し、「...が 親しい人?」のように利用できるものとして話を進める。
次のようなプログラムになる。
挨拶とは (名前 → ・)
名前は 文字列
名前に 入れ
名前が 親しい人?
ならば 「やあ、」を
さもなければ 「こんにちは、」を
つぎに
表示し 名前を 表示し 「さん。」を 表示すること。
このプログラムでは、名前を一旦変数に代入する必要がある。なぜなら、与えられた文字列データを2度使用する必要があるからである。1つは「親しい人?」に与えるデータとして、もう1つは「表示」に与えるデータとしてである。
このような場合、文字列データをいったん局所変数に代入しておき、この変数名を引用することで、何度でも参照できるようになる。
ところで、上のプログラムにある次の箇所に注目して欲しい。
[A]
・・・・・・・・
ならば 「やあ、」を
さもなければ 「こんにちは、」を
つぎに
表示し
・・・・・・・・
「表示」という処理単語を、「〜〜を 表示する」というパターンで覚えてしまうと案外、上のような記述は浮かびにくい(しかし上は日本語として不自然ではない!)。最初のうちは、
[B]
・・・・・・・・
ならば 「やあ、」を 表示し
さもなければ 「こんにちは、」を 表示し
つぎに
・・・・・・・・
と記述してしまうことが多いだろう。Bでも間違いではないが、Aの方が「表示」の使い方として簡素であり、Mind的なプログラミングである。
実体変数と情報変数の使い分け
ここまでで、「○○は文字列実体」という定義と、「○○は文字列」という定義の2種類について解説してきたが、これらはともに文字列データを格納するものなので、最初のうちは、いったいどちらを使えばよいのかと迷うかも知れない。
少し整理してみよう。
文字列実体型変数:
- 文字列の実体そのものを格納する
- メモリを消費する(格納する文字列のサイズ+4バイト)
- データの代入に多少時間がかかる
- 機能的にはオールマイティでありどのような操作にでも使用できる
文字列情報型変数:
- 文字列情報を格納する
- メモリ消費が少ない(文字列の長さに関係なく4バイト固定)
- データの代入がきわめて高速
- 文字列の追加など、いくつかの文字列操作(文字列を生成・合成・変換する系統)は使えない
おおざっぱであるが、最初のうちは次のような方針によるといいだろう。
- 大域変数として定義する場合:文字列実体型の変数を使う
- 局所変数として定義する場合:文字列情報型の変数を使う(ただし、文字列の追加など若干の文字列操作は適用できないので、その場合は文字列実体型とする)
上の指針には、根拠がある。
例えば、バスの乗客のうち、2列目から4列目の計3列(=文字列情報に相当)に乗っているのは自分の家族だ‥という主張をしたとする。しかしそのルールは次にやってくるバスについては適用できない‥という話に似ている。
大域変数は文字列実体型で定義することを勧める。大域変数はプログラム全体が動作している間、ずっと生きている変数なので、長時間その内容が保証されなくてはならないからである。
文字列情報変数への文字列代入で気になる例を示そう。
名前は 文字列。
名前を尋ねて記憶するとは (・ → ・)
「名前を入力してください:」を 表示し
文字列入力し 名前に 入れること。
上のプログラムは一応正しいが、少し危険でもある。その理由は、オペレータに尋ねた名前を格納するのに、文字列情報型の変数を使用しているからである。
処理単語「文字列入力」は標準ライブラリに備わっている単語で、機能としてキーボードから入力した文字列を「入力文字列」という、同じくライブラリ内に宣言した文字列実体型の変数に格納し、そこを指す文字列情報を利用者側に返すようになっている。あくまで文字列の実体は、「入力文字列」という大域の文字列実体変数にある。
さて、上のプログラムで「名前」を大域変数として宣言しているが、大域変数に格納するからには、少し時間が経過してから(言葉を換えれば、他の処理単語から)、これを参照しようという狙いがあるはずである。
もし、「名前」へ格納してからこれを参照するまでの間に、別の目的で「文字列入力」が実行されるようなことがあると、その瞬間、実体(「入力文字列」という文字列実体)が破壊されてしまい、「名前」に格納されている情報は無意味になってしまう。
したがって、このような場合には、「名前」は文字列実体として宣言するのが安全ということになる
。
一方、局所変数で文字列情報の変数を宣言する場合、局所変数が、その処理単語の実行中でのみ有効な短命の変数であることから、その処理単語を実行中に実体の方が換わってしまうというようなケースはきわめて低い。そのため、文字列データを情報だけで記憶してもほとんどの場合問題ないのである。
また、文字列情報型局所変数のそもそもの設置目的が、スタックに置かれている文字列データ(文字列情報)をちょっとの間退避することににあるので、その文字列情報を文字列情報型変数に代入するというのは筋が通っている。
まれな例ではあるが、短時間での局所変数としての文字列情報変数であっても、うまくいかない例をあげておく。
[C]
カップルの名前を尋ねるとは (・ → 男性名、女性名)
男性の名前は 文字列
女性の名前は 文字列
「男性の名前を入力してください:」を 表示し
文字列入力し 男性の名前に 入れ
「女性の名前を入力してください:」を 表示し
文字列入力し 女性の名前に 入れ
男性の名前と 女性の名前を 返すこと。
注7
プログラムの最後のところに、「...と ...を ...返すこと」という妙な記述があるが、「返す」はMind標準の擬似語であり動作上は無意味である。名詞を2つ並べただけで定義を終ると見た目の座りが悪いのでこうしているだけである。
このプログラムは期待通りには動作しない。正確にいうと、女性の名前だけ2つ返してしまう。理由は先に述べた通りで、2度目の「文字列入力」が、最初に入力した名前を格納しているライブラリ内の大域変数「入力文字列」(文字列実体)を破壊するからである。
この点だけ改良したものを示す。
[D]
カップルの名前を尋ねるとは (・ → 男性名、女性名)
男性の名前は 文字列実体 長さ 40桁 ←ここでは危険
女性の名前は 文字列実体 長さ 40桁 ←ここでは危険
「男性の名前を入力してください:」を 表示し
文字列入力し 男性の名前に 入れ
「女性の名前を入力してください:」を 表示し
文字列入力し 女性の名前に 入れ
男性の名前と 女性の名前を 返すこと。
実は D もうまくない。ほかのプログラムと混ぜて複雑にすると誤動作する。
局所変数として文字列実体を定義し、処理単語から戻る時にはそこを指す文字列情報を返していることが原因である。先に述べたように、局所変数は処理単語が動作している間だけ使うことのできる格納域であり、処理単語からリターンしてしまうと破棄されてしまう。
この点を再度改良したものが以下となる。
[E]
男性の名前は 文字列実体 長さ 40桁。 ←ここなら安全
女性の名前は 文字列実体 長さ 40桁。 ←ここなら安全
カップルの名前を尋ねるとは (・ → 男性名、女性名)
「男性の名前を入力してください:」を 表示し
文字列入力し 男性の名前に 入れ
「女性の名前を入力してください:」を 表示し
文字列入力し 女性の名前に 入れ
男性の名前と 女性の名前を 返すこと。
システムですでに定義されている変数は以下の通りである。(注:システムで定義済みという意味ではほかに、構造体や配列があるが別のセクションで述べる)
| 変数名 |
宣言 |
| 終了パラメータ |
(ワード変数) |
| 環境変数 |
(文字列実体 長さ 3072バイト) |
| 変換文字列 |
(文字列実体 長さ 2048バイト) |
| 入力文字列 |
(文字列実体 長さ 4096バイト) |
| 小数変換文字列 |
(文字列実体 長さ 22バイト) |
| 固定小数変換文字列 |
(文字列実体 長さ 60バイト) |
| 読み出し文字列 |
(文字列実体 長さ 4096バイト) |
この表の中で重要なものについて補足しておこう。
変数「入力文字列」は、処理単語「文字列入力」が内部で使用するもので、キーボードから入力した文字列をここに格納する。(処理単語が返すのはそこを指す文字列情報である)
このように、新たに発生した文字列データをスタックに返す処理単語は、その実体を内部に抱えた変数に格納し、スタックには文字列情報だけを返すようになっている。
類似のもので使用頻度の高いものを下記にまとめておく。
| 処理単語 |
返されるデータ |
実体が格納される大域変数名 |
| 文字列入力 |
文字列情報 |
「入力文字列」 |
| 一行読み出し |
文字列情報 |
「読み出し文字列」 |
文字列変換
桁数指定で文字列変換
文字列変換・バイト
文字列変換・ワード
文字列変換・ダブル |
文字列情報 |
「変換文字列」 |
| 文字列変換・小数形式 |
文字列情報 |
「固定小数変換文字列」 |
| 文字列変換・指数形式 |
文字列情報 |
「小数変換文字列」 |