web-dev-qa-db-ja.com

スタック指向の言語はどのような問題に適しているのでしょうか?

スタック指向プログラミング は、かなり広く使用されていないパラダイムです(まあ、 PostScript は、あちこちで内部的に使用されています)。これを念頭に置いて、スタック指向言語が得意とする問題は何ですか?彼らは[パラダイム]よりも何をしますか?また、どのような問題について、それらは悪い選択ですか?

スタック指向プログラミングはニッチなパラダイムですか?

8
Anto

スタック指向のプログラミング言語の主な問題は、人間にとって理解が難しいことです。利点は、それらが非常に簡単であり、コンピューターがおよび生成を評価できることです。

それがPostScriptに選ばれた理由です。プリンターが非常に少量のメモリと非常に能力不足のCPUしか持っていなかったのはそれほど前のことではありません。したがって、プログラムを解釈しやすく、生成も容易な言語で提供することで、評価するためにプリンター内にスーパーコンピューターを必要としませんでした。

また、現在の多くの言語は、スタック指向ではありませんが、実際にはスタック指向のバイトコードにコンパイルされます(Javaおよび.NETと考えてください)。繰り返しますが、その理由は、指向処理は、コンピュータが推論するのが非常に簡単です。

16
Dean Harding

Thorbjørnはすでにコンパイルについて要点を述べています-私が正しく覚えていれば、Javaバイトコードはスタック指向言語の例です。これは普遍的ではありませんが [〜#〜] llvm [〜#〜] は確かにスタックを持つ「静的単一代入」のものを使用しますが、ローカル変数アクセスと式の評価では、1回限りの書き込みが可能な不変の仮想レジスターモデルを使用します。 、これらのものは基本的に不変のポインタを保持します。

とにかく、スタック指向の言語は [〜#〜] lisp [〜#〜] -likeまたは [〜#〜] algol [〜#〜] =のような言語は、計算的に言えば、実行できます。スタックには暗黙的なメタデータが含まれる場合もあり、たとえば [〜#〜] ml [〜#〜] の型推論とほぼ同等の処理を実行します。たとえば、コンパイル時に1回実行することなく評価されます。時間プッシュまたはポップ。

本当の問題は可読性なので、問題はこれらのうちどれがあなたがより読みやすいと思うかです...

a * b + c * d
(+ (* a b) (* c d))
a b * c d * +

原則として、LISPのような接頭辞は括弧なしで実行できますが、演算子ごとに固定数の引数を使用する必要があります(postfixやinfixと同様)。以前の「腹立たしいほどかっこいい括弧がたくさん」というジョークにはいくつかの真実があると思いますが、オペレーターが最初に来る順序を維持しながら、それは回避できました。言い換えれば、受け入れるコンパイラを書くことができます...

+ * a b * c d

最も読みやすいものについては、明らかに議論の余地があります。 Infixは初心者には馴染みがありますが、これらのフォームに慣れるのにそれほど時間はかかりません。

個人的には、これがパラダイムとして数えられるとは確信していません。それは単なる表記法であり、意味上の影響はほとんどありません。たとえば、3つすべてのフォームは Yacc 文法を使用して処理できます。3つすべてがまったく同じ [〜#〜] ast [〜#〜] フォームを使用して、セマンティック分析とコード生成は、構文が「スタック指向」に見えるかどうかを知る必要さえありません。

[〜#〜]編集[〜#〜]

おっと-基本的なポイントは上にあると思いますが、私の答えを明確に述べる必要があると思います。基本的には、IMOにはこれらの表記法を支持する特定の問題がないということです。人々はどちらかを好むかもしれませんが、それは別のものです。

ただし、LISPプログラマーが指摘するのは、メタプログラミングはLISPのような表記で非常にうまく機能するということです。ただし、演​​算子が表示される場所ではなく、括弧についてです。ただし、許可される Forth のバリアント...

(1 2 3 4 +)

...と同じくらい良いでしょう。どちらの方法でもメリットは、コードを使用して操作する簡単な表記法です。これは、スタック指向の中間言語(バイトコードなど)が普及しているのと同じ理由です。間違いなく、ordering-agnostic ASTフォームの操作もかなり簡単に行うことができます。これは、パターンマッチングが Haskell およびMLで行うことの一種です。

[〜#〜] edit [〜#〜]-説明...

Postfix/stackベースのフォームを使用することは、まさにそれを意味します。たとえば、引数の順序の変更を意味するものではありません。次の例は、それらを表現するために使用される構文を除いて、すべて同等です。

(< 1 2)
(1 < 2)
(1 2 <)

注-演算子が後置であるという理由だけで、1と2の順序を入れ替える必要はありません。

(if (< a b) (handle a_smaller) (handle b_smaller_or_equal))

((a b <) (a_smaller handle) (b_smaller_or_equal handle) if)
((a_smaller handle) (b_smaller_or_equal handle) (a b <) if)

状態をifの近くに維持したい場合もあれば、そうでない場合もあります。どちらでもかまいません。

Forthはこれらの方法のどちらでもifを表現しませんが、postfix/stack指向の言語がそうできない理由はありません。 Forthは(少なくとも最初は)スタックで整数のみを許可していましたが、LISPが副作用の式をパラメーターとして渡すことを許可すると、接頭辞ではなく接頭辞とは関係ありません。 Postfix言語では、コードを引数として渡す(つまり、スタックにプッシュする)こともできます。

6
Steve314

私は長年にわたっていくつかのスタック指向言語を使用してきました。

大学では、システム管理者を1つの出力ページだけをレンダリングするのに非常に時間がかかるように見える小さな PostScript プログラムで混乱させていました。はい、私たちがアクセスしたレーザープリンターは、アカウントが与えられたミニコンピューターよりも浮動小数点のパワーが大きかったので、 mandelbrots を実行するのに最適でした。

transputers も使用しました。これらは、トランジスタごとのパフォーマンスに対して高度に最適化されたプロセッサでした。シリコンのすべてのビットはその重みを引く必要があったため、 ハフマンエンコード 命令セット(最も一般的な命令は1バイトでコーディングされていました)があり、従来のレジスタセットではなく、スタックのペアがありました。 。 1つのスタックは優先度が低く、もう1つは高かったため、コンテキストの切り替え時間(優先度の低いプロセスから優先度の高いプロセス)がミリ秒ではなくマイクロ秒単位で測定されました。

また、組み込みの Forth プロセッサを使用するいくつかのロボットシステムにも取り組み、Forthはマシンコードのように動作しました。必要に応じて2倍のCPUを購入し、パフォーマンスに応じてそれらをビニングし、システムに組み込むのに最適な半分を選択することを覚えています。これは、速度で評価された単一のチップを購入するよりも、評価されていないチップを購入する方が安かったからです。私たちはそれらを実行する必要がありました。 * 8 ')

2
Mark Booth

フォースはほとんど死んでいると思います。 Jさんもいますが、それが大きな影響を与えているかどうかはわかりません。ポストスクリプトは実際には人間によるプログラミングには使用されていませんね。つまり、スタック指向の言語は事実上存在しなくなったと思います。

私が見る限り、これらはスタック指向のハードウェアアーキテクチャでのアセンブラの代替として適しています。ファームウェアなど。しかし、そのようなハードウェアがポスト16ビットプロセッサ領域にもう存在するかどうかはわかりません。

0
Ingo