レッスン2

スタック

7と4と1を、間に空白を入れて一行で打ち込んでください。
7 4 1<ENTER>
<ENTER>キーを押した後、スタックディスプレイは次のように見えるはずです。:
Stack: depth 3
1
4
7
三つの数字の間の空白(あるいはデリミター)は、Mopsに、これらは三つの別個の数値であるということが意図されている、ということを伝えます。(空白を一つ、でなければならないわけではありません。二つ以上つながった空白やTABキーでもかまいません。) 上と異なって、もし714と打ち込んだのなら、一個の数値である741がスタック上に置かれたでしょう。 数(など)が、どのように入力され、スタック上に格納されるのかを理解することは重要です。

スタックがどのように働くのかをはっきりさせる一番の方法は、よく使われるアナロジーですが、カフェテリアでよく見かける、バネ式お盆給仕機を用いる方法です。 バネつき台の上に盆を一枚のせると、そのお盆は一番上からとるとき最初の盆になるのは明らかでしょう。 しかし、二番目の盆を最初の盆の上にのせたならば、二番目の盆の重みで最初の盆は押し下げられ、列の次の客が一番上から取るときの盆は、二番目の盆になります。 言い換えると、スタックの上に最後に置かれたものが、最初に取り出されるものになるのです。 (コンピュータ用語ではLIFOと呼ばれ、"Last In, First Out"【後入れ先出】を意味します。)
この原理がMopsのスタックにも適用できることがわかるでしょう。というのは、初めに入力した数7はスタックの底にあり、一番最近入力した数1は一番上にあるからです。

どうすれば、スタックから数を取り除くことができるでしょうか? 一つの方法は、あなたが数を入力したときにしたことと反対のことをするMopsワードを使うことです—これはスタックから数を取り除き、スクリーンの下方部分のカーソルが点滅している場所に、その数を"タイプ" (ないしプリント)します。 このワードとは、単なる.(ピリオド。"ドット"と読みます)です。 これを打ち込んでみましょう:
.<ENTER>
1
ここで起ったことは、ドット(スクリーンにタイプ)コマンドが1をスタックの頂上から抜き取り、それを"タイプ"したということでした。 スタックディスプレイは、二つの数(4と7)がまだスタックに残っていることを示しています。

別の言い方をすれば、あなたがスタック上の数についてドットオペレーションを実施するといつでも、その数はスタックから取り除かれ、"タイプ"されるということです。—つまり、それは現行の(current)ウィンドウに表示されます。 (上の例でのように)Mopsウィンドウが現行ウィンドウであれば、"タイプ"される数はどれもカーソルポジションに現れるでしょう。これはまさに、あなた自身がキーボードにそれをタイプしたときと同じようになります。

Mopsプロンプト【に該当する点滅カーソル】を、混乱を避けるために左端に寄せるには、単にRETURNを(ENTERではありません!)一回押すだけです。 (改行(キャリッジリターン)は、あなたがプログラマとしてMopsにそのプリントを命じない限り、自動的にプリントされることはありません。少し後に、そのやり方を見るでしょう。)

今度は、二つのピリオドを、間に空白を挟んでタイプし、ENTERを押してみましょう。
. .<ENTER>
4 7
Mopsは、残った二つの数を、スタックから取り除いた順序でプリントしました。 7はスタックの一番底にあったことを思い出してください。; そのため、それはスタックから取り出される最後の数となったのであり、Mopsプロンプト(点滅カーソル)が再び現れる前の最後のアイテムとしてスクリーン上に表示されたのです。 ごらんのように、複数のドットコマンドは、スタックの頂上から引き続いて数値を取り除き、スクリーン上の左から右にそれらをプリントします。また、最後のドットコマンドが実行されたときには、スタックには何も残っていないことにも、注意してください。

Mopsは、.S("ドットエス"と読みます)というワードも持っています。これは、スタック上にある全ての数値を、それらを取り除くことなく表示するものです。 これは、プログラムが走行している間に使うと便利でしょう。というのは、ウィンドウの上方にあるスタックディスプレイを見るためにプログラムを止めたくはないこともありうるからです。 また、スタックに、スタックディスプレイに入り切らない程たくさんのアイテムがあるかもしれません。 スタックには、Mopsウィンドウの上方部分の空間に表示できるよりも、ずっと多くのアイテムを保持することができるのです。しかし、その場合でも、.S を使えば、全てのスタックアイテムが、ウィンドウの下方部分にタイプされるのです。

それがどのように働くのかを見るため、前に使ったのと同じ三つの数値をスタック上に置いてください (間の空白をお忘れなく。):
7 4 1<ENTER>
そして、.S を打ち込めば、スクリーンはこのようになるでしょう:
.s<ENTER>
Stack: depth 3
       1   $     1
       4   $     4
       7   $     7
ドル記号($)の左の数字は10進表現ですが、 右側の数字は16進表現です。 このリストのドル記号は16進であることを示すものなのです。 この場合には、たまたまスタック上の数値がどちらの基数でも同じなのです。 スタックディスプレイは三つの数値がまだスタック上にあることを示していることにも注意してください。 通常の . は一つの数値を、表示し、同時に取り除きますが、 .S は全ての数値を、どれひとつ取り除くことなく表示する、ということです。

数値をスタック上に置き、それらを.S オペレーションで確かめ、その後、一つずつ、 または続けてプリントしつつ取り除く、という手順で、スタック上の操作を実験してみてください。 手間を減らす追加的方法として、 ドットコマンドの後に、CRコマンドを使うことができます---これは、 改行("Carriage Return")の略号です。 ひとつ以上の . コマンドの後に、CRをコマンドとして打ち込めば(最後のピリオドとCRの間の空白をお忘れなく)、Mopsプロンプト【カーソル】は次の行の左端に戻ります。

例えば:
1 10 100<ENTER>
. . . cr<ENTER>
100 10 1 
| 
もし、たまたま、スタック上の数値の個数よりも一つ多く . コマンドを実行してしまったなら、 Mopsは、(警告ビープ音とともに、)スタックが空っぽである【のにアイテムを取り除こうとした】というメッセージを送るでしょう。 害はないので、試してみましょう。
1 10 100<ENTER>
. . . . cr<ENTER>
100 10 1 171

Error # -4 stack underflow
. . . . cr
       ^
Current object: TW class: MLTEFWIND

【ちなみに、最後に吐き出されている171はスタックの底を示すマーカーで、起動時に積み込まれます。hex ABです。】

スタックは、パラメタースタックとも呼ばれます(ときどき、データスタックということもあります。)。 その理由は、Mopsの多くの演算が、それが実施できるようになる前に、 一つまたは複数の値がスタック上に存在していることを必要するからです。 これらの値は、コンピュータ用語ではパラメター(引数)と呼ばれ、 演算に渡される、とか手渡されるなどと言われるのです。 実際、演算はスタックに対して自分が必要な数をもとめ、それを取り除きます。

スクリーン上にプリントされるべき値をスタックが保有しているとき、パラメターがどのように働くのかについて、 前の節で少し見ました。 パラメタースタックは、言い方を変えれば、多くの演算が依存する値を積み込む一種のコンテナです。 この観念は、Mopsがどのように基本算術を遂行するのかを論じた後には、より明瞭になるでしょう。

スタック算術

もしヒューレット-パッカードのRPN計算機をお使いの経験があれば、 まず二つの数値を打ち込んで、それから、足し算には"+"、あるいは、かけ算には"*"といった、実施したい演算の記号の描かれた キーを押す、という方法はもうご存知でしょう。 これをしているとき、実は、スタック型のコンピュータを利用しているのです。

HPのRPN計算機を使ったことのない方のために、数2 を数 7に加算するときの手順を書いておきましょう。 【下の手順表の原文は辻褄が合わない気がするので(多分ミスプリント)、勝手に直しておきました。絶対の自信があるわけではない(RPN計算機を使ったことはない)ので、そのうち、ちょっと聞いてみます。】

7 キーを押します。 7 がスタックのトップに置かれ、ディスプレイにプリントされます。
ENTER キーを押します。これは 7を、HP 計算機のスタックのあと1セルだけ深いところに押し込みます。 それは計算機の記憶装置の中にあり、その記憶装置は、値を、それが演算に必要になるまで、一時的に保管するところです。
それから2 キーを押します。これは2 をスタックのトップに置きます。
最後に + キーを押します。これはスタックから各値(最初に7、それから 2)を読み取り、 これらを足し合わせます。
答、9は、ディスプレイとスタック上の両方に現れ、必要なら、さらなる演算に供されます。
Mopsもこれに非常によく似た動き方をします。

一歩一歩、二つの数を足し合わせるやり方を述べるなら、それは、各数をスタックに一回一個ずつ置いていき、 それから + キーを押す、というようなものになるでしょう。それは次のようになります。:
7
2
+
. cr
9
| 
(各行の終わりにENTER を押すことは、もう、言うまでもありませんよね。)

ここで何が起ったのか追跡してみましょう。

数をタイプしてENTERを押す毎に、スタックカウンターがどのように増えていくのかについては、もうお分かりでしょう。 三行目で、演算、つまり足し算記号 "+" を打ち込んでいます。 ここでENTERを押すと、コンピュータはあなたのために、スタックにある上の二つの数の和を計算し、 その和をスタックに格納してくれます。(したがって、スタックディスプレイは、スタック上の一つの数を示します。) もともとあった数は、加法演算によってスタックから取り除かれることにも注意してください。 というよりむしろ、ほんの一瞬の間ですが、二つの数がコンピュータ内で加算処理されている間は、スタック上には何も無いのです。 【老婆心ですが:足し算のような単純な演算では、この説明は微妙ですが、もっと一般の複雑な演算処理(サブルーチン)の場合には、まさに上のように考えることができる場合が多くなります。】 スタックの内容(この場合は、足し算の結果)を表示するためには、 .("ドット")コマンドを発行しなければなりません。 もちろん、答9がスタックに置かれていたわけです。

Mopsでは、これらの操作全てを、もっと単純な一行命令の形式で行うことができます。各要素の間に少なくとも一つの空白が必要なだけです。 それは次のようになるでしょう。:
7 2 + . cr
9
| 
この一行命令は、前のものと同じコマンドを一つ一つ順に含んだものになっていますが、ずっと打ち込みやすいものになっています。 この方法でやると不便といえるは、スタックディスプレイを一歩一歩読み取ることができなくなる、といったことぐらいでしょう。 しかし、結局は、重要なのは答えであり、一時的なスタックの途中経過ではないはずです。


チュートリアル目次へ
前へ < レッスン1 次へ > レッスン3


最終更新:2018年12月04日 09:08