変数を変更できる言語と同じようにクロージャを使用します。違いは明らかです(通常は)変更することはできません。
次は(皮肉なことに、私は今で書いています)Clojureの中で、簡単な例です:
(let [a 10
f (fn [b]
(+ a b))]
(println (f 4))) ; Prints "14"
このような場合、閉鎖の主な利点は、私が「部分的に適用する」ことが可能です関数を呼び出す必要があります(多くのシナリオでは非常に便利です)。以下の例では、すぐに関数を呼びたくない場合はどうなりますか? f
が呼び出されたときに利用できるように、a
を渡す必要があります。
しかし、あなたはそれが必要(@Bergiが指摘するように、この例では「悪」である、けれども)とみなされる場合、あなたはまた、ミックスにいくつかの可変性を追加することができます。
(let [a (atom 10) ; Atoms are mutable
f (fn [b]
(do
(swap! a inc) ; Increment a
(+ @a b)))]
(println (f 4)) ; Prints "15"
(println (f 4))); Prints "16"
この方法では、静的エミュレートすることができます変数。これを使ってmemoize
のようなクールなことをすることができます。これは、「静的変数」を使用して、参照関数を透過する関数の入出力をキャッシュします。これによりメモリ使用量は増加しますが、正しく使用するとCPU時間を節約できます。
私は状態を持っているという考えに反することに同意しなければなりません。国家は悪ではない。彼らは必要ですです。すべてのプログラムには状態があります。グローバルな、可変状態は悪いです。
また、はに変更可能であり、機能的にはまだプログラムです。リスト上にマップを含む関数があるとします。また、マッピング中はアキュムレータを維持する必要があります。
- スイッチ
fold
へmap
:私は本当に( "手動でそれをやって" 無視して)2つのオプションがあります。
- 変更可能な変数を作成し、マッピング中に変更します。
オプション1が望ましいはずですが、これらの方法の両方を機能プログラミング中に利用することができます。ある関数が内部的に可変変数を使用していても、 "関数外"という観点からは違いはありません。この関数は、影響を受ける変更可能な状態のみが関数に対して局所的であり、外部に何らかの影響を与えることができないため、依然として参照を透過的かつ純粋にすることができます。ローカル変数を変異
例コード:
(defn mut-fn [xs]
(let [a (atom 0)]
(map
(fn [x]
(swap! a inc) ; Increment a
(+ x @a)) ; Set the accumulator to x + a
xs)))
注変数a
関数外部から見えないができ、それが有する任意の効果は決してグローバル変化を引き起こすことができます。関数は各入力に対して同じ出力を生成するので、実質的に純粋です。
あなたがコーディングしているパラダイムにかかわらず、あなたは常に**状態を持っています。 **常に**。状態は悪くない、それは完全に必要です。邪悪とは、変化する世界的な状態です。あまりにも多くを包含しようとする州(神の目的)である。 – Carcigenicate
OK。この男は閉鎖とは何かを説明します。 https://www.youtube.com/watch?v=7aYS9PcAITQ#t=18m13s 彼の例では、very_local_variableは「邪悪な」状態だと思います。最初にc1()を呼び出すと、それ以降は同じように呼び出されるので、同じではありません。それぞれの呼び出しは「世界を変える」でしょう。だから...おそらくこの2番目の例(クロージャの説明付き)はあまり正確ではないでしょうか? – LancerX
突然変異している状態が関数の外にある場合、それは悪と見なすことができます。私の答えで私の新しい編集を見てください。あなたはグローバルな状態に影響を与えずに変更可能であり、それは関数の外で何も変更していないので悪ではありません。この機能は依然として効果的で機能的であり、参照性があります。 – Carcigenicate