lisp(clojure)-変数を深く理解する


本文はlarryligqから作成します.転載は出所を明記してください.http://blog.csdn.net/larrylgq/article/details/7395261
作者:リュウガン
メールボックス:[email protected]
clojureにおける変数は、語法変数とダイナミック変数(dynamic)に分類され、他の言語の局所変数とグローバル変数に類似しています.
一つの変数は、保存タイプを宣言する必要がない値を保存できる名前の位置です.どのタイプの値も保存できます.これらの値は運行期間検査のためのタイプ情報を持っています.そしてタイプが間違ったら動的に検出されます.
eg:(数値以外のオブジェクトを+関数に伝えました.)
この点から見て、lispは強いタイプで、ダイナミックなタイプの言語です.
lispは値を伝えるものですが、伝達する値は対象の参照です.これはjava、pythonと似ています.変数がオブジェクトを参照する変数に適用される変数を意味します.
 
新しい変数を導入する方法は、関数のイメージを通して、関数が呼び出されたときに実行する変数を定義します.
eg:(defn foo[x y z](+x y z)
関数が呼出されるたびに、clojureは新しいバインディングを作成し、使用者によって伝達された実際の参照を保存します.このバインディングのライフサイクルは運行期間終了までです.(再帰関数の参照は、関数が呼び出されるたびに結合されます.)
 
もう一つの新しい変数を導入する方法は、let特殊オペレータを使用することである.
eg:(let[variable*]body-form*)
variableは初値を賦与してもいいし、賦課しなくてもいいです.次はletでx、y、zをそれぞれ1、2、nilに結び付けます.
(let[x 1][y 2]z]
…)
 let関数は、匿名関数を呼び出すマクロであり、上記の例は(fn[x y z](…))1 2 nilに展開することができる.
letは、呼び出しが終了した後、その変数がletの前に参照されている場合、参照されたオブジェクトを再び指します.関数定義とletという2つの形態をバインディング形式と呼び、複数のネストが同名変数に対するバインディングを行い、内層の変数バインディングは外層をカバーします.
clojureのクローズド
匿名関数が閉鎖されたスコープの変数を参照すると、このようになります.
(let[count 0]璢(fn[](inc count))))
スコーンの参照は、ロールドメイン規則に従ってLamda式で合法的であり、countを参照した匿名関数は、戻り値としてlet関数によって返されます.
この表式で作成したクローズドがグローバル変数に与えられる場合、
(def*fn*(let[count 0]33751;(fn[](inc count))
これで外部で呼び出すことができます.
USER>(*fn*)
1
USER>(*fn*)
2
もちろんこれ以外の複数のクローズドも同じ変数を参照できます.
たとえば:
(let[count 0]
 (リスト
  #(fn[](inc count)
  #(fn[])
  #(fn[]count)
 )
)
 
ダイナミック変数
Clojureには4種類のダイナミック変数があります.Vars、Refs、Atoms、Agents.
以下の表はそれらの間の比較です.
 この表の関数は後で紹介します.
 
Var
Ref
Atom
Agent
目的
ローカルスレッドに対する変数の変更を同期します.
同期は1つ以上の動的変数に対して変更されます.
同期して変数を変更します.
変数を非同期に変更します.
作成方法(def name initial-value)(ref initial-value)(atom initial-value)(agent initial-value)変更方法(def name new-value)は、関数の参照(alter-var-root
(var name) update-fn args)
を使用して、変数に新しい値を割り当てます.(set! name new-value) binding ,
(ref-set ref new-value) , dosync (alter ref
update-fn arguments
)
ref , dosync , , 142は、refの値を修正するためには、dosync内で呼び出す必要があり、トランザクションの開始後に値が変化しても、現在のトランザクションは再試行されない.(commute ref
update-fn arguments
)
は、古い値がどうであれ、新しい値(reset! atom new-value) (compare-and-set! atom current-value new-value) current-value true, false 142を保存します.(swap! atom
update-fn arguments
) compare-and-set! , false
が使用するスレッド池は、(java.util.co ncurrent.Exectors.newFixedThreadPool)スレッドの個数がcpu個数+2 (send agent
update-fn arguments
)
である.
  
注:
1:Software Transation Memory(STM):
STM事務で行う修正は、事務提出後にしか他のスレッドに見られない.ACIDの中のA(原子性)とI(分離性)を実現した.
事務開始後、他のスレッドがこのRefに対して変更されたら、事務は開始状態に戻ります.これはC(一致性)を実現します.
2:sendはAgentにactionを割り当てた後、すぐに戻ります.action運転が終了したら、Agentに戻ります.使用するスレッド池は、(java.util.co ncurrent.Exectors.newFixedPool)スレッドの個数はcpu個数+2 sendoffとsetに似ています.使用するスレッド池は、Exadur.スレッドの個数は実際の必要に応じて割り当てられます.sendでは、send-off関数が事務で呼び出されます.actionはスレッドが提出されるまで待ちます.他のスレッドに送信されて実行されます.