純粋に機能的、変異、状態変化などのサブルーチンを明確に区別する言語?


8

最近、私が使用してきたほとんどの最新のプログラミング言語(C / C ++、C#、F#、Ruby、Python、JSなど)では、何を決定するための言語サポートがあったとしてもごくわずかであることに、ますます苛立ちを感じていますサブルーチンが実際に行います。

次の単純な疑似コードを考えてみます。

var x = DoSomethingWith(y);

DoSomethingWith(y)への呼び出しが実際に何を行うかをどのように判断しますか?それのmutateますyは、またはそれはのコピーを返しますyは?グローバルまたはローカルの状態に依存していますか、それともyにのみ依存していますか?グローバルまたはローカルの状態が変わりますか?閉鎖は通話の結果にどのように影響しますか?

私が遭遇したすべての言語で、これらの質問のほとんどは、サブルーチンのシグネチャを見ただけでは答えられず、コンパイル時または実行時のサポートもほとんどありません。通常、唯一の方法は、APIの作成者に信頼を置くことであり、ドキュメントや命名規則が、サブルーチンが実際に何をするかを明らかにすることを期待しています。

私の質問はこれです 。今日、これらのタイプのシナリオを象徴的に区別し、実際に記述できるコードにコンパイル時の制約を課す言語はありますか?

(もちろん、スコープやクロージャのレベルの違い、静的コードとインスタンスコードの分離、ラムダ関数などのように、ほとんどの現代の言語ではこれに対するいくつかのサポートがあります。しかし、これらは互いに衝突するように見えることがあまりにも多いです。たとえば、ラムダ関数は通常、純粋に機能し、入力パラメーターに基づいて値を返すか、何らかの方法で入力パラメーターを変更します。しかし、通常は、ラムダ関数から静的変数にアクセスすることができます。インスタンス変数へのアクセスを許可すると、すべてがバラバラになります。)


1
「完全に機能」はあいまいであることに注意してください。あなたはおそらく「純粋」(副作用のない)を意味します。「関数型」とは、関数をファーストクラスのオブジェクトとして扱い、高次関数を可能にするプログラミングパラダイムを意味します。これらの関数は必ずしも純粋である必要はなく、ほとんどの関数型プログラミング言語は不純な関数を許可します。
tdammers

それは重要な意味上の違いのように聞こえます。関数とは、数学的な意味です。つまり、ルーチンは入力データにのみ依存し、プログラムの他のデータの読み取りや書き込みは行いません。これを説明するには、「純粋な関数」の方が正しい用語ですか。
Christian Palmstierna

回答:


10

はい、あなたはHaskellを見たいです。それはまさにあなたが望むものを行います。すべての関数はデフォルトで純粋であり、モナドを使用してのみ状態を変更できます。また、Haskellはあらゆる種類のものについて非常に強い静保証ありhttp://learnyouahaskell.com/を


ああ!私はHaskellについて多くの良いことを聞きましたが、それを深く掘り下げるのに慣れていません。多分それは私の請求書に合うでしょう:)
クリスチャンパルムスティエナ

それは多くの興味深いことが起こっているところのようです
Zachary K

5
モナドは状態を他のデータ型以上に変更することはできません。それらは他の言語と同じ純粋性の制約に拘束されます。結局のところ、いくつかの構文糖を除いて、それらについて特別なものは何もありません。彼らができることは、連鎖または再帰的な関数呼び出しを介して状態を蓄積するコードの便利な抽象化を提供し、ランタイムに対してコンパイルされると、そのようなコードは、モナディックコードのように命令型コードに要約されます。ただし、それはまだ抽象概念であり、コードは100%純粋です。
tdammers

4
また、関数はデフォルトでは純粋ではなく、純粋なピリオドです。Haskellは不純な関数を表現できません。
tdammers

3
@CPX:少なくとも3つのHaskell用の強力なWebフレームワーク(Yesod、Happstack、およびSnap)と、言及する実質的にすべてのタスク用の豊富なライブラリ(SOAPについては不明)があります。Haskellエコシステム内の平均コード品質は優れている傾向があります。私が予測できる最大の問題は、より長いメンテナンス期間にわたってそのようなことをサポートするのに十分なプログラマーを見つけることです。
tdammers

6

CおよびC ++は、constキーワードによる問題の少なくとも一部に対するサポートを非常に制限しています。これだけでは純度を制御できませんが、(特にC ++で)特定のデータ構造を特定のポインターを介して変更しないようコンパイラーに指示するために使用できます。一部のコンパイラ(gccなど)も、純粋を完全に実施するための言語拡張として「pure」属性を提供しています。(詳細については、この質問を参照してください)。

Dのプログラミング言語は、明示的な機能の純度を宣言するためのサポートがあり、コンパイラはチェックして(つまり、純粋関数内から非純粋関数を呼び出すしようとすると、コンパイルエラーを生成する)純度を強制されます。

Haskellは完全に純粋です。つまり、言語自体は不純な関数を表現できず、「ルーチン」という概念はありません。純粋な関数だけを使用して解決できないものは、(純粋でない)ランタイムに外部委託されます。副作用のあるプログラムは、プログラムの動作を記述する遅延データ構造を(純粋な構造のみを使用して)構築し、それをランタイムに渡すことによって実装されます。Haskellコミュニティは、プログラミング言語の動物園全体を積極的に実験しています。

もっとあるかもしれませんが、これらは私がよく知っているものです。


gccは、そのような
役に立たない

クラスに非constメンバー関数がない場合、C ++のconstメンバー関数は純粋性を制御します。すべてのデータは一定になり、すべてが純粋に機能します。
tp1

@ tp1:違います。constメンバー関数は、他のクラスの非const静的メソッドを呼び出したり、他のクラスをインスタンス化したり、単純にフリー関数を呼び出したり、グローバル変数を変更したりすることで、簡単に副作用を生成できます。これは、使用するすべてのライブラリ(STLを含む)を含め、コードベース全体をall-constにロックした場合にのみ機能します。
tdammers

@tdammers:データはコンストラクターのパラメーターによって異なる値に初期化できるため、全定数ロックダウンはそれほど悪くありません。ただし、すべてのデータがグローバル変数ではなくクラス内にある必要があります。
tp1

@ tp1:安全に使用できるライブラリの数が実質的にゼロになるため、これも非常に非現実的です。
tdammers 2012年

1

フェリックスには3つのカテゴリがあります。

  1. 機能

    There is a rule for functions: 
    
    A function introduced by a fun binder is not allowed to have any side effects.
    
    The compiler does not enforce this rule, but it does take advantage of it when
    optimising your code. 
    
  2. 手続き

    Procedures do not return a value, and may and generally should have side-effects.
    
  3. 発電機

    A generator is a function that may have side effects.
    

これは、私が求めていることを正確に実行しようとする言語のように聞こえます。ただし、関数がコンパイラーによって強制されないのは残念です(数年後に専門的に作業してから、他のプログラマーのライブラリーに対してひどく不信感を抱きました;-))。また、非常に新しいので、いじくり回すかもしれませんが、商業的/専門的な開発の候補のようには思えません:(
Christian Palmstierna

1
@ChristianPalmstierna:この何年も前の質問に出くわしただけです。残念ながら、非常に多くの興味深いプロパティと同様に、関数が純粋かどうかを判断することは、停止問題を解決することと同じです。これは必ずしも実行できないことを意味するのではなく、コンパイラーが純粋性を証明できない純粋な関数が無限に存在することを意味するため、そうでない場合でも不純として拒否する必要があります。(ただし、これは静的型チェックと同じです。通常、安全であるが型セーフであると証明できないプログラムは無数にあります。入力を止めることはありません。)
JörgW Mittag
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.