タグ付けされた質問 「pure-function」

純粋な関数は、同じ引数が与えられると常に同じものに評価され、変更したり、外部状態に依存したりすることができない関数です。

6
メモ化された純粋な関数自体は純粋と見なされますか?
たとえばfn(x)、の素因数のリストを返すなど、高価な処理を行う純粋な関数だとしますx。 そして、と呼ばれる同じ関数のメモバージョンを作成するとしmemoizedFn(x)ます。特定の入力に対して常に同じ結果を返しますが、パフォーマンスを向上させるために以前の結果のプライベートキャッシュを維持します。 正式に言えば、memoizedFn(x)純粋と見なされますか? または、FPディスカッションでそのような関数を参照するために使用される他の名前または修飾用語はありますか?(つまり、後続の呼び出しの計算の複雑さに影響する可能性があるが、戻り値には影響しない可能性がある副作用を持つ関数。

7
同じ入力が常に同じ出力を返すだけでなく、副作用がある関数を何と呼びますか?
次のような通常の純粋な関数があるとします function add(a, b) { return a + b } そして、副作用があるように変更します function add(a, b) { writeToDatabase(Math.random()) return a + b; } 私の知る限り、純粋な関数とは見なされていません。なぜなら、人々は純粋な関数を「副作用のない関数」と呼ぶことがよくあるからです。ただし、同じ入力に対して同じ出力を返すという点では、純粋な関数のように動作します。 このタイプの関数には別の名前がありますか、名前が付けられていないのですか、それとも実際には純粋であり、純度の定義について間違っていますか?

5
例外をキャッチ/スローすると、純粋なメソッドが不純になりますか?
次のコード例は、私の質問の背景を示しています。 Roomクラスはデリゲートで初期化されます。Roomクラスの最初の実装では、例外をスローするデリゲートに対するガードはありません。このような例外は、デリゲートが評価されるNorthプロパティにバブルアップします(注:Main()メソッドは、クライアントコードでRoomインスタンスがどのように使用されるかを示します)。 public sealed class Room { private readonly Func<Room> north; public Room(Func<Room> north) { this.north = north; } public Room North { get { return this.north(); } } public static void Main(string[] args) { Func<Room> evilDelegate = () => { throw new Exception(); }; var kitchen = new Room(north: …

4
純粋な機能を非公開にする正当な理由はありますか?
同僚と少し議論をしました。簡単に言えば、純粋な関数を非表示/カプセル化する正当な理由はありますか? 「純粋」とは、ウィキペディアの定義を意味します。 同じ入力から常に同じ結果を返します。(この説明のために、値のセマンティクスがないFoo Create(){ return new Foo(); }場合Fooは不純であると見なされます。) 可変状態(ローカル変数を除く)またはI / Oは使用しません。 副作用を引き起こしません。

2
コンストラクターで[Pure]を使用する場合
.NETのコードコントラクトについて学び、純粋なコンストラクターの概念を理解しようとしています。コードの契約ドキュメントの状態: コントラクト内で呼び出されるすべてのメソッドは純粋でなければなりません。つまり、既存の状態を更新してはなりません。純粋メソッドでは、純粋メソッドへのエントリ後に作成されたオブジェクトを変更できます。 そして、PureAttributeドキュメントの状態: 型またはメソッドが純粋であること、つまり、目に見える状態の変更を行わないことを示します。 メソッドに関してはこれらのステートメントを理解していますが、コンストラクターはどうですか?次のようなクラスがあったとします: public class Foo { public int Value { get; set; } public Foo(int value) { this.Value = value; } } このコンストラクターは明らかに新しいFooオブジェクトの状態に影響しますが、他の副作用はありません(たとえば、パラメーターを操作したり、非純粋なメソッドを呼び出したりしません)。これは候補者[Pure]ですか?[Pure]コンストラクターに属性を配置することの意義は何ですか?また、自分のコードでこれをいつ行う必要がありますか?

5
関数をパラメーターとして使用する場合、関数はすぐに不純ですか?
入力パラメーターの純度は実行時まで不明であるため、関数を入力パラメーターとして使用する場合、関数はすぐに不純であると見なされますか? 関連:関数が関数の外部で定義されているが、パラメーターとして渡されない純粋な関数を適用する場合、副作用がなく、出力のみが入力のみに依存するという基準を満たしている場合でも純粋ですか? コンテキストについては、JavaScriptで機能コードを作成しています。

6
純粋に機能的なものと伝えるもの、尋ねないでください?
「関数の理想的な引数の数はゼロです」は明らかに間違っています。引数の理想的な数は、関数に副作用がないようにするために必要な数です。それよりも少ないと、機能が不必要に不必要になり、成功の穴から離れて痛みの勾配を登らざるを得なくなります。時々、「ボブおじさん」が彼のアドバイスにスポットを当てています。時々彼は見事に間違っています。彼のゼロ引数アドバイスは後者の例です (ソース:このサイトの別の質問の下での@David Arnoによるコメント) コメントには133の賛成票があります。そのため、そのメリットにもっと注意を払いたいと思います。 私が知っている限りでは、プログラミングには2つの別々の方法があります:純粋な関数型プログラミング(このコメントが奨励するもの)と伝える、尋ねない(このWebサイトでも時々推奨されています)。私の知る限り、これらの2つの原則は基本的に互換性がなく、互いに反対に近いものです。副作用しかありません」。また、純粋なファンシトンが機能的パラダイムのコアと考えられているのに、聞かないで、OOパラダイムのコアと考えられていると思ったので、私はちょっと困惑しています。 開発者はおそらくこれらのパラダイムのいずれかを選択し、それに固執すべきでしょうか?まあ、私は自分を決して従わせることができなかったことを認めなければなりません。多くの場合、値を返すのが便利だと思われ、副作用でのみ達成したいことをどのように達成できるか本当にわかりません。多くの場合、副作用があると便利に思えますが、値を返すだけで達成したいことをどのように達成できるか本当にわかりません。また、しばしば(これは恐ろしいことだと思います)両方を行うメソッドがあります。 しかし、これらの133の賛成票から、私は現在純粋な関数型プログラミングが「勝っている」と推論しています。これは正しいです? したがって、このアンチパターンに乗ったゲームの例で私が作ろうとしているのは、純粋に機能的なパラダイムに準拠させるためにそれを実現したい場合、どうすればいいのでしょうか?! 戦闘状態にあることは私にとって理にかなっているようです。これはターンベースのゲームであるため、私は辞書に戦闘状態を保持します(マルチプレイヤー-同時に多くのプレイヤーがプレイする多くの戦闘があるかもしれません)。プレーヤーが順番を回すたびに、(a)状態を適宜変更し、(b)更新をプレーヤーに返します。これは、JSONにシリアル化され、基本的に、ボード。これは、両方の原則に同時に違反していると思われます。 OK-本当にやりたいなら、メソッドをその場で修正するのではなく、戦闘状態に戻すことができます。だが!それから、完全に新しい状態を変更するのではなく、単に戻すために、戦闘状態のすべてを不必要にコピーする必要がありますか? おそらく、移動が攻撃である場合、HPが更新されたキャラクターを返すことができますか?問題は、それほど単純ではないことです。ゲームのルール、動きは、プレイヤーのHPの一部を削除するだけでなく、多くの場合、より多くの効果をもたらします。たとえば、キャラクター間の距離を広げたり、特殊効果を適用したりすることができます。 私はその場で状態を変更して更新を返す方がはるかに簡単に思えます... しかし、経験豊富なエンジニアはこれにどのように取り組むでしょうか?

3
「メソッドは値を返すか副作用があるはずですが、両方ではありません」の起源
私は一度、メソッドには戻り値があり(参照的に透過的)、または副作用がありますが、両方ではないことを読みました。このルールへの参照は見つかりませんが、それについてもっと学びたいです。 このアドバイスの起源は何ですか?どの人またはコミュニティからそれが生じましたか? 追加クレジット:このアドバイスに従うことの利点は何ですか?

5
関数が純粋かどうかを計算する
ウィキペディアによると: コンピュータープログラミングでは、関数に関するこれらのステートメントの両方が成立する場合、関数は純粋であると説明できます。関数は、同じ引数値が与えられると常に同じ結果値を評価します。関数の結果値は、プログラムの実行が進むにつれて、またはプログラムの異なる実行間で変化する可能性のある隠された情報や状態に依存することも、I / Oデバイスからの外部入力に依存することもできません。結果を評価しても、可変オブジェクトの変更やI / Oデバイスへの出力など、意味的に観察可能な副作用や出力は発生しません。 関数が純粋であるかどうかを計算する関数を書くことができるかどうか疑問に思っています。JavaScriptのコード例: function sum(a,b) { return a+b; } function say(x){ console.log(x); } isPure(sum) // True isPure(say) // False

2
関数型プログラミングは、同じオブジェクトが複数の場所から参照される状況をどのように処理しますか?
人々(このサイトでも)が日常的に関数型プログラミングのパラダイムを称賛していることを読んで聞いています。特に、C#、Java、C ++などの従来の命令型オブジェクト指向言語でも、プログラマーにこれを強制するHaskellのような純粋に関数型の言語だけでなく、このアプローチを提案します。 変異性と副作用が便利だと思うので、理解するのは難しいと思います。しかし、人々が現在副作用を非難し、可能な限りそれらを取り除くことが良い習慣であると考えると、私が有能なプログラマーになりたいなら、私はパラダイムのいくつかのより良い理解に向けて私の夢を始めなければならないと信じています...したがって、私のQ. 機能的パラダイムで問題を見つけたときの1つの場所は、オブジェクトが複数の場所から自然に参照されるときです。2つの例で説明します。 最初の例は、私が暇なときに作ろうとしているC#ゲームです。これはターンベースのWebゲームで、両方のプレイヤーに4つのモンスターのチームがあり、チームからモンスターを戦場に送ることができます。戦場では、相手のプレイヤーが送ったモンスターと対戦します。プレイヤーは戦場からモンスターを呼び戻し、それらを自分のチームの別のモンスターに置き換えることができます(ポケモンと同様に)。 この設定では、単一のモンスターを少なくとも2か所から自然に参照できます。プレイヤーのチームと2つの「アクティブな」モンスターを参照する戦場です。 ここで、1つのモンスターがヒットし、ヘルスポイントが20失われる状況を考えてみましょう。命令パラダイムの括弧内で、このモンスターのhealthフィールドを変更して、この変更を反映させます。これが私が現在行っていることです。ただし、これによりMonsterクラスが変更可能になり、関連する関数(メソッド)が不純になります。これは、現時点では悪い習慣と考えられています。 私は自分にこのゲームのコードを理想的な状態ではない状態にして、実際に将来のある時点でそれを完成させるという希望を持たせる許可を与えましたが、それがどのようにあるべきかを知り、理解したいと思います適切に書かれた。したがって、これが設計上の欠陥である場合、どのように修正すればよいですか? 機能的なスタイルでは、私が理解しているように、代わりにこのMonsterオブジェクトのコピーを作成し、この1つのフィールドを除いて古いオブジェクトと同じにします。suffer_hitこのメソッドは、古いオブジェクトを変更する代わりに、この新しいオブジェクトを返します。次に、同様にBattlefieldオブジェクトをコピーし、このモンスター以外のすべてのフィールドを同じに保ちます。 これには少なくとも2つの困難が伴います。 階層は、この単純化された単なるBattlefield->の例よりもはるかに深くすることができますMonster。1つを除くすべてのフィールドをこのようにコピーし、新しいオブジェクトをこの階層全体で返す必要があります。これはボイラープレートのコードです。関数型プログラミングはボイラープレートを減らすことになっているので、私は特に迷惑です。 ただし、さらに深刻な問題は、データが同期されなくなることです。フィールドのアクティブなモンスターは、体力が低下します。ただし、この同じモンスターは、その制御プレイヤーから参照されTeam、そうではありません。代わりに命令型のスタイルを採用した場合、データのすべての変更はコードの他のすべての場所から即座に表示され、このような場合には非常に便利ですが、これを実現する方法はまさに人々が言うことです命令型スタイルとは間違っています! これでTeam、各攻撃の後に旅をすることで、この問題に対処できるようになります。これは余分な作業です。しかし、後でさらに多くの場所からモンスターが突然参照される可能性がある場合はどうなりますか?たとえば、モンスターがフィールド上にある必要のない別のモンスターに集中できるようにする能力が付いている場合はどうなりますか(実際にそのような能力を検討しています)。私はウィル確かに immediatellyそれぞれの攻撃の後にも焦点を当てたモンスターへの旅を取ることを覚えていますか?これは時限爆弾のようで、コードが複雑になると爆発するため、解決策はないと思います。 より良い解決策のアイデアは、同じ問題にぶつかったときの2番目の例から生まれます。学界では、Haskellで独自のデザインの言語の通訳を書くように言われました。(これは私がFPとは何かを理解し始めることを余儀なくされた方法でもあります)。クロージャーを実装しているときに問題が発生しました。もう一度同じスコープは現在、複数の場所から参照することができます。この範囲を保持する変数を通じおよびネストされたスコープの親スコープとして!明らかに、それを指している参照のいずれかを介してこのスコープに変更が加えられた場合、この変更は他のすべての参照からも見える必要があります。 私が付いた解決策は、各スコープにIDを割り当て、Stateモナド内のすべてのスコープの中央辞書を保持することでした。これで、変数はスコープ自体ではなく、バインドされたスコープのIDのみを保持し、ネストされたスコープは親スコープのIDも保持するようになります。 私のモンスターバトルゲームでも同じアプローチが試みられると思います...フィールドとチームはモンスターを参照していません。代わりに、中央のモンスターディクショナリに保存されているモンスターのIDを保持しています。 ただし、問題の解決策として躊躇せずにそれを受け入れることができないというこのアプローチの問題をもう一度見ることができます。 これもまた、ボイラープレートコードのソースです。これにより、1行が必ず3行になります。以前は単一フィールドの1行のインプレース変更でしたが、現在は(a)中央ディクショナリからオブジェクトを取得する(b)変更を加える(c)新しいオブジェクトを保存する中央の辞書に。また、参照の代わりにオブジェクトと中央の辞書のIDを保持すると、複雑さが増します。FPは複雑さと定型コードを減らすために宣伝されているので、これは私が間違っていることを示唆しています。 さらに深刻な2番目の問題についても書きました。このアプローチではメモリリークが発生します。到達できないオブジェクトは、通常、ガベージコレクションされます。ただし、到達可能なオブジェクトがこの特定のIDを参照していない場合でも、中央の辞書に保持されているオブジェクトをガベージコレクションすることはできません。また、理論的に注意深いプログラミングによりメモリリークを回避できます(各オブジェクトが不要になったら、手動で中央ディクショナリから削除することもできます)が、これはエラーが発生しやすく、FPはプログラムの正確さを高めるようにアドバタイズされます。正しい方法ではありません。 しかし、解決された問題であるように思われました。WeakHashMapこの問題の解決に使用できるJavaが提供しています。C#も同様の機能を提供します。ConditionalWeakTableただし、ドキュメントによると、コンパイラによる使用を目的としています。そしてHaskellにはSystem.Mem.Weakがあります。 そのような辞書を保存することは、この問題の正しい機能的な解決策ですか、それとも私が見落としているより単純なものがありますか?そのような辞書の数は簡単に増えてひどくなります。したがって、これらのディクショナリも不変であると想定されている場合、これは多くのパラメータを渡すことを意味します。または、それをサポートする言語では、モナド計算が行われます。これは、ディクショナリがモナドで保持されるためです(ただし、私は純粋に関数でそれを読んでいます)このディクショナリソリューションはほとんどすべてのコードをStateモナド内に配置しますが、これは正しいソリューションであるかどうかを疑います。 いくつか検討した後、もう1つ質問を追加します。このような辞書を作成することで何が得られるのでしょうか。多くの専門家によると、命令型プログラミングの問題点は、一部のオブジェクトの変更が他のコードに伝播することです。この問題を解決するために、オブジェクトは不変であると想定されています-このため、私が正しく理解していれば、オブジェクトに加えられた変更は他の場所には表示されないはずです。しかし、今は古くなったデータで動作する他のコードが気になるので、中央の辞書を発明して...もう一度、いくつかのコードの変更が他のコードに伝播するようにします!したがって、想定されるすべての欠点を伴う命令型のスタイルに戻りませんか?

3
関数型プログラミングで代入演算子またはループの使用が推奨されないのはなぜですか?
私の関数が2つの要件を満たしている場合、Sum リスト内の項目の合計を返す関数は、特定の条件に対して項目がtrueと評価され、純粋な関数と呼ばれる資格があると思いますか? 1)特定のi / pのセットに対して、関数が呼び出された時間に関係なく、同じo / pが返されます 2)副作用はありません public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){ int result = 0; foreach(var item in numbers) if(predicate(item)) result += item; return result; } 例: Sum(x=>x%2==0, new List<int> {1,2,3,4,5...100}); 私がこの質問をしている理由は、必須のプログラミングスタイルであるため、代入演算子とループを回避するようアドバイスしている人がほとんどいるためです。では、関数プログラミングのコンテキストでループと代入演算子を使用する上記の例で何が問題になるのでしょうか?

4
この方法は純粋ですか?
次の拡張メソッドがあります。 public static IEnumerable<T> Apply<T>( [NotNull] this IEnumerable<T> source, [NotNull] Action<T> action) where T : class { source.CheckArgumentNull("source"); action.CheckArgumentNull("action"); return source.ApplyIterator(action); } private static IEnumerable<T> ApplyIterator<T>(this IEnumerable<T> source, Action<T> action) where T : class { foreach (var item in source) { action(item); yield return item; } } シーケンスの各アイテムにアクションを適用してから、それを返します。 このメソッドにPure(Resharperアノテーションからの)属性を適用する必要があるかどうか疑問に思っていました。そのためと反対の引数を確認できます。 長所: …

4
純粋な関数に暗黙的に依存しているのは悪いことですか(特にテストの場合)?
タイトルを少し拡張するために、他の関数またはクラスが依存する純粋な関数を明示的に宣言する(つまり注入する)必要があるかどうかについて、結論を出そうとしています。 それらが要求せずに純粋な関数を使用する場合、テスト可能性が低く、設計が悪い特定のコードはありますか?私は単純なものから純粋な機能の任意の種類のために、問題の結論に取得したいと思い、ネイティブ関数(例えばmax()、min()-言語に関係なく)今度は他の純粋な機能に暗黙的に依存してもよいことを習慣に、より複雑なもの。 通常の懸念は、一部のコードが依存関係を直接使用するだけの場合、それを単独でテストすることができない、つまり、あなたが黙って持ってきたものすべてを同時にテストすることです。しかし、これは、小さな関数ごとに実行する必要がある場合、かなりのボイラープレートを追加するので、これがまだ純粋な関数に当てはまるかどうか、なぜか、またはなぜそうでないのかと思います。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.