質問

値を返すメソッドと返さないメソッドを区別する言語があるのはなぜですか?

i.e。 OracleのPL / SQLでは、関数とプロシージャの主な違いは、関数が値を返す必要があり、プロシージャは値を返さないことです。

そうではない言語の場合、なぜですか?


編集:この質問を読んでいる人の興味を引くかもしれない関連する質問を見つけました:

役に立ちましたか?

解決

コンピューターサイエンスの理論と実践の当初の概念では、関数とサブルーチンは事実上互いに関係がありませんでした。

FORTRANは通常、これらの両方を実装し、その違いを実証した最初の言語として知られています。 (初期のLISPもこれにやや反対の役割を果たしましたが、学問以外の影響はほとんどありませんでした)。

数学の伝統(CSは60年代にまだ含まれていた)に基づいて、関数は値をより大きな式に戻すことのみを目的としたパラメーター化された数学的計算のカプセル化としてのみ見られました。 「裸」と呼べること(F = AZIMUTH(SECONDS))は単なる些細なユースケースでした。

一方、サブルーチンは、何らかの効果をもたらすことを意図したステートメントのグループに名前を付ける方法と見なされていました。パラメーターは使いやすさを大きく向上させ、変更されたパラメーター値を返すことを許可された唯一の理由は、グローバル変数に依存せずにステータスを報告できるようにすることでした。

つまり、カプセル化とパラメーター以外の概念的な接続は実際にはありませんでした。

本当の問題は、「どうしてそんなに多くの開発者が同じものと見なすようになったのですか?」

そしてその答えはCです。

K + Rが最初にPDP-11用の高レベルマクロアセンブラ型言語を設計したとき(PDP-8で開始された可能性がありますか?)、ハードウェアの独立性の妄想はありませんでした。ほぼすべての「ユニーク」この言語の機能は、PDPマシンの言語とアーキテクチャを反映したものでした(i ++および--iを参照)。これらの1つは、呼び出し側がサブルーチンの戻り値(R0 [、R1])を無視したことを除いて、関数とサブルーチンをPDPで同様に実装できる(常に実装する)ことでした。

このようにボイドポインターが生まれ、C言語がプログラミングの世界全体を引き継いだ後、このHW / OS実装アーティファクト(ほとんどすべての後続プラットフォームで当てはまるが)が言語セマンティクスと同じであるという誤解がありました。

他のヒント

純粋な設定または効果タイプの設定では、明らかに「何も返さない」メソッドが原因で、違いの世界があります。副作用に対してのみ有用です。

これは、式とステートメントの区別に類似しており、言語を整理し、通常見落とされがちなプログラムのクラスを排除することができます(もちろん、Cがそれを行わない理由は;))。

小さな例を挙げると、式と文を明確に区別する場合、 if(x == 3) if(x == 3)ではなく構文的に正しくありません(式が必要なステートメントを使用するため)および単なる型エラーではありません(ブール値が必要な整数を使用するため)。これには、割り当てが右オペランドの値を持つ式であるコンテキストで、タイプベースのルールによって許可される if(x = true)も許可しないという利点があります。

モナドで効果をカプセル化する言語では、重要な違いは次のようになります。

  • 純粋な関数である()を返す関数で、()または発散と呼ばれる無駄な空の値を1つだけ返すことができます
  • " result"のない関数である IO()(または他のモナドの単位)を返す関数IO(またはいずれか)モナドの効果を除く

2年前の質問、特に自分の言語Felix http:// felix-langに固有の質問に答えてください。 org が、とにかくここに行きます:)

Felixでは、関数とプロシージャは根本的に異なり、プロシージャには副作用があり、ステートメントで呼び出されるだけではありませんが、関数には副作用がなく、式で使用されます(Felixにはジェネレーターがあるため、副作用のある関数です..:)

いいえ、主にパフォーマンス上の理由で実行モデルは根本的に異なりますが、完全ではありません。モデルは次のとおりです。

  • 関数は、マシンスタックに戻りアドレスを入れ、戻り値も入れます。
  • プロシージャは、ヒープ上のリンクリストを使用します。手続き型コードはフラットで、マシンスタックを使用しません。

これは一般的に非効率的ですが、なぜそうするのですか?答えは次のとおりです。Felixの手順はすべて潜在的にコルーチン(繊維)です。チャネルにアクセスすることにより、制御を別の手順に切り替えることができます。これにより、制御が交換されます。

  • パフォーマンス上の理由から、コントロール交換でマシンスタックをコピーすることはオプションではありません。
  • メモリ管理上の理由から、スタックポインタのスワップもオプションではありません。

OSは通常、スレッドのスタックポインターをスワップしますが、これはかなり高速ですが、リニアアドレスマシンでは根本的な問題があります。スタックの最大サイズを途方もなく小さな値に制限するか、スレッドの数を制限する必要があります途方もなく小さな値に。 32ビットマシンでは、このソリューションを検討するのに十分なアドレス空間がありません。 64ビットマシンでは、スタックスワッピングの可能性が高くなりますが、もちろん、ユーザーの要求は、ハードウェアがリリースされてから3日後にハードウェアを上回るようになります..:)

Felixはヒープベースのスタックへの単一のポインターをスワップするだけなので、コンテキストスイッチは途方もなく高速であり、アドレス空間の無駄はほとんどありません。もちろん、プロシージャコールでのヒープ割り当てです。

コンパイラでは、理論モデルの多くのアーキテクチャが「as-if」で最適化されて離れています。基礎なので、実際のパフォーマンスと実装は理論モデルとはかなり異なる可能性があります。ただし、コンパイラーは違いを見分けることができないことを証明できれば....余暇でコーヒーを飲む機会を拒否される以外は:)

だから、ここでは、なぜ関数と手続きが異なって扱われるのかについて異なる答えがあります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top