レッスン11

特殊な演算操作

【以下【】の中は訳者が付け足したものです。】

そろそろ、基礎的なMops演算操作を他にもいくつか学んでおくべきでしょう。それらは、かなり単純なので、ここで特別に触れておいても良いでしょう。ここではあまり詳しくは言いませんが、すこし自分で試してみれば、どのように働くのか、感じがつかめるでしょう。

第一の演算グループは、パラメタースタック上の上二つのアイテムの値を比較するものです。比較の結果がスタック上に置かれます。次のものが含まれます。:

MIN ( n1 n2 -- n-min ) ‘n1’ と ‘n2’ の小さい方をスタック上に残します。
MAX ( n1 n2 -- n-max ) ‘n1’ と ‘n2’ の大きい方をスタック上の残します。
次のグループは、整数の符号の正負を操作します。ひとつは、スタックの一番上の数の絶対値(正)を返します。もうひとつは、スタックの一番上の数値の符号を変えます。:もとの数が正ならばそれを負に変え、負ならば正に変えるということです。次の演算子がそれです。:
ABS ( n -- |n| ) ‘n’ の絶対値をスタックに残します。
NEGATE ( n -- -n ) スタック最上位の値の符号を変えます。

続いては、簡単な算術の簡略形です。これらの意味は自明だと思います。
1+ ( n -- n+1 ) スタック最上位の数値に1を加算します。
1- ( n -- n-1 ) スタック最上位の数を1減らします。
2+ ( n -- n+2 ) スタック最上位の数値に2を加算します。
2- ( n -- n-2 ) スタック最上位の数値を2減らします。
2* ( n -- 2n ) スタック最上位の数値を2倍します。
2/ ( n -- n/2 ) スタック最上位の数値を2で割ります。
3+ ( n -- n+3 ) スタック最上位の数に3を加算します。
3- ( n -- n-3 ) スタック最上位の数値を3減らします。
4+ ( n -- n+4 ) スタック最上位の数値に4を加算します。
4- ( n -- n-4 ) スタック最上位の数値を4減らします。
4* ( n -- 4n ) スタック最上位の数値を4倍します。
4/ ( n -- n/4 ) スタック最上位の数値を4で割ります。
これらの短縮系の適用は、Mopsでプログラミングすればする程、多くみられるようになるでしょう。 加法と減法の短縮系は、例えば、何らかの種類のカウンターを増やしたり減らしたりする必要がある場合に役立ちます。

テキストの表示

このチュートリアルでは、これまでは、数値をスクリーン上に表示するのに、. (ドット)コマンドを用いてきました。しかし、ひとつのプログラムにおいて何度も、テキストもスクリーン上に表示したいと思うことでしょう。それはある種の指示を表示するものかもしれませんし、純然たる数字の解答が何を表したものなのかを説明することによって、プログラムをユーザーフレンドリーにしようとするものかもしれません。後者である場合には、通常は、解答の数値は実行毎に異なるかもしれませんが、それに付帯して固定的なテキストのメッセージを表示するでしょう。テキストそれ自体については、Mopsワードである ." (ドット-クォートと読みます)を使うことができます。この後に必要なテキストメッセージを続け、最後にクォーテーションマーク(引用符) (")です。

Mopsでは、多くのコンピュータ言語におけるのと同様、引用符は、区切り文字(delimiter)として知られる、広いシンボルカテゴリーに該当します。というのは、これらは、何かを区切る(delimit)あるいはその限界を置くからです。— この場合はテキストメッセージが区切られます。この区切り文字セットの中にあるテキストは、テキスト文字列あるいは単に文字列と呼ばれます。通常のMopsワードでは、半角空白、タブ文字、あるいは改行は区切り文字です。しかし、メッセージ文字列については、普通は、半角空白文字も文字列の一部ととして含めたいので、その代わりに"を区切り文字として用いるのです。 しかし、." はMopsワードですので、空白で区切られていなければなりません。この空白は、文字列には含まれません。しかし、ひとつの空白の後の最初の文字が、(空白であったとしても)その文字列の最初の文字になります。例を挙げましょう。:
: HI  ." Hello, this is Mops operating on the Mac." cr  ;
今や、HIとMopsプロンプトの前で入力すれば、引用符の間の文字列がスクリーン上に現れます。 ここでも、." の直後の空白はメッセージの一部ではなく、." をMopsが認識できるワードとして区切るためにのみ働いていることに注意してください。もしもここに空白がなければ、Mopsは「."hello,」を1ワードとして解釈しようとするでしょう。これは明らかに、私達の望んだことではありません。

Mopsの良いところのひとつとして、新しいワードの定義の中で、以前に定義したワードを利用できるということがあります。ですから、ここで定義した HI を、もうひとつのMops定義の中に含ませることができます。例えば、
: GREETING   hi ." How are you?" cr  ;
とすれば、GREETING をMopsプロンプトで打ち込んだときにはいつも、HIのメッセージだけではなく、追加的テキストも表示します。

さて、算術演算とテキスト列に関する知識を合わせて、前のレッスンでの計算のワード ADD を"人間化"してみましょう。 新しい定義はつぎのようになります。:
: ADD ( n1 n2 -- )  + ." The sum is:" .rc  ;
あるいは、前のレッスンのADDがまだ定義されているなら(そして、トリッキーなことをしたいなら)、次のようにもできます。:
: ADD ( n1 n2 -- )  ." The sum is: " add  ;
新しいワードを利用するには、Mopsプロンプトで次のようなコマンドを発行します:
10 20 add
The sum is: 30

明示的なスタック操作

名前付き入力引数と局所変数は、多くのスタック操作を隠してくれますが、スタック上のアイテムの順序のせいで、特定の演算操作のために、いくつかの値を明示的に動かす必要がある場合もあり得ます。逆に、スタック上に単純にもう必要のない数値があって、処分したいこともあるかも知れません。このような場合には、一連のスタック操作演算子の中から選ぶことができます。

次の三つのスタック操作演算子は、心に留めておくべきでしょう。:
SWAP ( n1 n2 -- n2 n1 ) パラメタースタック上の上二つのアイテムの順序を入れ替えます。
DUP ( n -- n n ) トップスタックアイテムを複製して、新しいコピーを上におきます。
DROP ( n -- ) トップスタックアイテムを取り除きます。この直下にもうひとつアイテムがあった場合、それがトップアイテムになります。
SWAP は、例えば、二つの値がスタック上にあるのに、引き算や割り算をするのに順序が違っている場合のような、 もっと複雑な定義の中で用いられます。 実際、これは、レッスン3で引用された問題のためのあまりエレガントでない定義で用いることもできました。:
 5 * 12 * 50
-------------
     40
分母をスタックの底(最初の入力)におけば、全てのかけ算を実行してから、スタック上に残った二つの数値の順序を入れ替えて、それから正しく割り算をすることができます。新しい演算は:
40 5 12 50 * * swap /
これを計算するワード定義は:
: FORMULA3 ( denom num1 num2 num3 -- solution )
  * * swap /  ;
DUP は、特定の計算のときに便利なことがあります。DUP の働き方を示す一つの例は、数の二乗を計算するのに利用することです。 二つの同じ数値をスタックに置くのではなく、一つだけをおいてそれを複製し、それからスタック上の二つの値をかけ算するのです。:
4 dup *

同じように、三乗計算は次のように行います:
4 dup dup * *

したがって、三乗計算を行うMopsワード CUBEDは次のようにセットアップできるでしょう。:
: CUBED ( n -- )  dup dup * * . cr  ;
このとき、‘3 cubed’ とMopsプロンプトからタイプすれば、次のように答えがスクリーン上に現れるでしょう。:
3 cubed
27

上に述べたこれら以外のスタック操作演算子について、実験してみてください。いくつかの数値をスタックにおき、コマンドを実行して、Mopsウィンドウのスタックディスプレイで、何が起るのかを観察してください。必要なら、計算上の要請に応じて、二つ、またはそれ以上のスタック操作演算子を、同じMopsワード定義内に集めることもできます。

しかし、概していえば、名前付き入力引数と局所変数の方が複雑な定義内でスタック上の値を操縦するのには好ましく、それらを用いたプログラムの方が、明示的なスタック操作(ときとして、スタックジムナスティックと呼ばれます【ジムナスティックは「体操」ですが、軽業、曲芸、無理(無闇)に動かすという語感でしょうか】)を用いるプログラムより、追跡がしやすく、デバッグが容易になります。そして、名前付き引数と局所変数の方が、より直観的なので、まず最初に間違いをおかすことが少なくなります。


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



最終更新:2018年12月04日 22:23