問題タブ [lexical-closures]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
javascript - JavaScript のレキシカル スコープ/クロージャ
「js」の関数には字句スコープがあることを理解しています(つまり、関数は、実行時ではなく定義時に環境(スコープ)を作成します)。
「f()」だけを実行すると、内部関数が返されます。私が得たのは、それが 'return' の機能です!
「ReferenceError: b が定義されていません」というメッセージが表示されるのはなぜですか? しかし、上記の内部関数はそのスペース、f() のスペースなどにアクセスできません。「b」がグローバル スペースに返されているため、console.log() は機能しませんか?
ただし、「f()」を新しい変数に割り当てて実行すると、次のようになります。
これは「barb」である「b」を返しますが、console.log() を再度実行すると、「ReferenceError: 'b' is not defined」が返されます。'b' が返されたので、グローバル スコープに含まれていませんか? では、なぜ 'x()' も 'f()' と同じように内部関数を返さなかったのでしょうか?
lisp - Common Lisp と Scheme のレキシカル クロージャの違い
Common Lisp では、次のコードのスニペットを (SBCL で) 構文エラーを通知されることなく評価できます。
対応するコードのスキーム スニペットを評価しようとすると (DrRacket で):
構文エラーを通知します。
これがSchemeで実行できない理由を誰かが知っていますか?
clojure - Clojureの閉鎖効率?
かなり頻繁に、私は交換します!新しい値を計算する際に 1 つ以上の外部値を使用する無名関数を使用するアトム値。これを行うには 2 つの方法があります。1 つはクロージャーであり、もう 1 つはそうではありません。
以下は、変数の数値をアトムに追加する簡単な例です。両方のアプローチを示しています。
これはでっち上げの例であり、もちろん、この特定の問題を解決するためにこのコードを実際に記述することはありません。理由は次のとおりです。
追加の機能を必要とせずに同じことを行います。
しかし、より複雑なケースでは、関数が必要であり、疑問が生じます。私にとって、この問題を解決する 2 つの方法は、コーディングの観点からはほぼ同じ複雑さです。その場合、どちらを優先する必要がありますか? 私の作業上の仮定は、非クロージャ方式の方が優れているということです (コンパイラが実装するのが簡単だからです)。
この問題を解決する 3 つ目の方法があります。これは、無名関数を使用しないことです。別の名前付き関数を使用する場合、クロージャーを使用することはできず、問題は発生しません。しかし、無名関数をインライン化すると、コードが読みやすくなることがよくあるので、そのパターンをツールキットに残しておきたいと思います。
ありがとう!
以下のA.Webbの回答に応じて編集します(これは長すぎてコメントに入れることができませんでした):
質問での「効率」という言葉の使用は誤解を招くものでした。より良い言葉は「エレガンス」または「シンプルさ」だったかもしれません。
Clojure について私が気に入っている点の 1 つは、他の言語では特定のアルゴリズムをより高速に実行するコードを作成できる一方で、慣用的な Clojure コードを作成すると、かなり高速になり、シンプルでエレガントで保守しやすいことです。 . 解決しようとしている問題が複雑になるにつれて、単純さ、優雅さ、保守性がますます重要になります。IMO、Clojure は、この意味で、複雑な問題の全範囲を解決するための最も「効率的な」ツールです。
私の質問は本当に - この問題を解決する方法が 2 つありますが、より慣用的で Clojure 風の方法は何ですか? 私がその質問をするとき、2 つのアプローチがどれだけ「速い」かが 1 つの考慮事項です。それは最も重要なものではありませんが、これが一般的なパターンであり、さまざまなアプローチが他の観点からの洗い流しである場合、それは正当な考慮事項であると私は思います. 以下の A. Webb の回答は、「おっと! 雑草から引き戻せ! コンパイラはどちらのアプローチも問題なく処理し、ターゲット プラットフォームなどの雑草に深く入り込まない限り、各アプローチの相対的な効率を知ることはできません。 . したがって、言語の名前からヒントを得て、そうするのが理にかなっている場合は、クロージャーを使用してください。"
2014 年 4 月 10 日の最終編集
A. Webb の回答を承認済みとしてマークしますが、A. Webb の回答と omiel の回答は本当に受け入れていますが、残念ながら両方を受け入れることはできません。無償の。
私が Clojure で気に入っている点の 1 つは、Clojure で共同作業を行う人々のコミュニティです。コンピュータ言語を学ぶということは、コードの構文を学ぶということだけではありません。より根本的には、問題について考えて理解するパターンを学ぶということです。Clojure とその背後にある Lisp には、信じられないほど強力な一連のパターンがあります。たとえば、ホモイコニシティ (「データとしてのコード」) は、マクロを使用してコンパイル時にコードを動的に生成できることを意味します。また、分解により、複雑なデータ構造を簡潔かつ読みやすくアンパックできます。どのパターンも Clojure に固有のものではありませんが、Clojure は問題解決を楽しくする方法ですべてをまとめています。そして、それらのパターンを学ぶ唯一の方法は、すでにそれらを知っていて使用している人々から学ぶことです. 1 年以上前に Clojure を初めて選んだとき、私が Scala やその他の候補よりも Clojure を選んだ理由の 1 つは、Clojure コミュニティーが有益で建設的であるという評判だったからです。そして、私はがっかりしたことはありません - 私の質問に関するこのやり取りは、StackOverflow や他の場所の他の多くの人と同じように、コミュニティが私のような初心者を助けようとしている様子を示しています - ありがとう!
javascript - PHPクロージャ関数:クロージャが無名関数でなければならないのはなぜですか?
ラムダまたは無名関数は、名前のない単なる関数です。
例えば
クロージャーは、パラメーター リストで指定されていない変数にアクセスできる関数です。PHP 5.3+ では、これらの変数は use キーワードの後に指定され、クロージャ関数の関数定義が実行されるときに値または参照によってリンクされます。
例えば
JavaScript では、関数がネストされている場合、スコープ チェーンが存在するという意味で、すべての関数はクロージャーです。たとえば、最も内側の関数は、1. そのローカル変数、2. として知られる、それを囲むスコープ内の関数のローカル変数にアクセスできます。そのクロージャ スコープ、3. クロージャ スコープのクロージャ スコープとして知られる、エンクロージング スコープのエンクロージング スコープのローカル変数、...、など、N にもアクセスできるようになるまで続きます。最上位のスコープ。最も内側のスコープで var を使用して宣言された変数は、外側のスコープの変数をマスクします。それ以外の場合、最も内側の変数が外側のスコープのものと同じ名前を持ち、var で宣言されていない場合、外側のスコープの変数が使用されます。
これは、次の PHP コードと同等です。
これについてはすべてここで説明します。
ここで私の質問です。なぜPHPのクロージャーはラムダ関数でなければならないのですか? JavaScript では、すべての関数がクロージャーですが、ラムダ関数である必要はありません。では、なぜ PHP で次のことができないのでしょうか?
(致命的なエラー: 構文エラー、予期しない T_USE、';' または '{' が必要です)
javascript - Javascript での締めのニュアンス
私は Javascript の関数合成手法を理解しようとしてきましたが、私の質問を示すためにおもちゃの準 MVC の彼の作業コードを思いつきました:
このコードでは、「フック」変数をバインドし、スコープがそのバインディングを保持する関数を返す関数を渡しています。これが私の質問の核心です。
「フック」バインディングを抽象化できるようにしたいので、「状態」バインディング関数を「フック」バインディングを行う関数に渡すだけです。Javascript が提供する遅延バインディング機能 (これを適用/呼び出す) を使用してそれを行う方法がわかりません。オブジェクト参照を渡して状態を維持し、作業を完了することができますが、これを解決するためのより機能的なアプローチに興味があります。そう:
a) Javascript の基本的なクロージャーでやろうとしていることを行う方法はありますか?
b) 遅延バインディングの「this」ベースのメソッドを使用する必要がある場合、最善のアプローチは何ですか? これは、Javascript で関数の状態を一般化するための実証済みの正しい方法だと思いますが、これを行うために書いているコードは役に立たなくなります。
r - それぞれが関数の親環境を変更する独立した関数呼び出しを並列化する
各呼び出しが関数の親環境を変更する、繰り返される独立した関数呼び出しを並列化する方法を見つけたいと思います。関数の各実行は独立していますが、さまざまな理由から、関数の親環境の変更に依存しない他の実装を検討することができません。以下の簡単な例を参照してください。親環境のコピーを各ノードに渡す方法はありますか? これをLinuxシステムで実行しています。
javascript - javascriptはどのクロージャー変数を割り当てますか?
私はさらに JavaScript のメモリ リークに飛び込みました。Ilya Kantorの記事を読んでいるときに、私の疑問が生じました。
Ilya が指摘しているように、DOM/COM オブジェクトと JavaScript オブジェクトの間の循環参照によって引き起こされる ie のメモリ リークを認識しています。
私はまた、デビッド・グラッサーによって説明されたシングルトンとして実装されている内部関数のレキシカル環境によって引き起こされるメモリリークを認識しています。
私の場合は異なります。次の例には参照がありませんが、どの JavaScript エンジンがリークするか、つまりのレキシカル環境
にdata
割り当てますか?data
wrapped
wrapped
への参照はありませんdata
data=null
とにかく漏れないように設定する必要がありますか?
Ilya の発言 (data
に設定されている場合null
)
現在、データは LexicalEnvironment のプロパティとしてメモリ内に残っていますが、それほど多くのスペースを占有していません。
デビッド 言う
幸いなことに、JavaScript の実装 (または少なくとも現在の Chrome) は
data
[wrapped
...]
Scott Christopher は、彼の回答で、同じではないにしても同様の質問を提起しました。
これは漠然としすぎています。明確な答えがあれば最高です。setInterval
上記の方法を実行しているときに、誰かが ie-vm で mem-usage グラフを描画したことさえありfactory
ますか?
bash - クロージャーは親関数名を取得します
Bash は「一種の関数型プログラミング言語」であり、クラスはありません。Closuresでカプセル化を使用することができましたが、親/スーパー/ベース関数も見つけるためにイントロスペクションを行いたいと思いdocker_
ます(これを正しく定義するためにコメントを追加することがわかっている場合)。
私はこれを管理しましたが、汚いハックsuper=${FUNCNAME}
でした。種類を使用する解決策はありますPARENT_FUNCNAME
か? 私はそのようなファイルdocker_.shを持っています:
いくつかの結果を得ました:
解決済み
使用する
コード:
いくつかの結果を得ました: