`
xiuzhuchenqing
  • 浏览: 15824 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Clojure的方言:ClojureScript中的引用类型

 
阅读更多

在百度百科中是这么定义引用类型的:“引用类型 由类型的实际值引用(类似于指针)表示的数据类型。如果为某个变量分配一个引用类型,则该变量将引用(或“指向”)原始值。不创建任何副本。引用类型包括类、接口、委托和装箱值类型”。Clojure的引用类型也于此类似。由于在Clojure中,纯函数式的可谓德高望重,备受推崇,也就意味着要尽量少用或者不用那些具有副作用特性的代码。但对数据状态的更改难以避免,毕竟事物总是变化的,因此Clojure中专门定义了一种引用类型。

 

以下中英文互译内容参考自Clojure - Functional Programming for the JVM

 

Reference types are mutable references to immutable data. There are four references types in Clojure: VarsRefsAtoms and Agents. They have many things in common:

引用类型是非易变数据的可变引用。Clojure中有四种引用类型: VarsRefsAtoms  Agents。他们具有一些共同点:

<!--[if !supportLists]-->·         <!--[endif]-->They can hold any kind of object.

他们能够持有任意类型的对象。

<!--[if !supportLists]-->·         <!--[endif]-->They can be dereferenced to retrieve the object they hold with the deref function or the @ reader macro.

使用deref函数或者@读取器宏能够间接引用他们以获取他们所持有的对象。

<!--[if !supportLists]-->·         <!--[endif]-->They support validators which are functions that are invoked when the value changes. If the new value is valid, they return true. Otherwise they either return false or throw an exception. If they simply return false, an IllegalStateException with the message "Invalid reference state" will be thrown.

他们都支持使用一种被称作为验证器的函数,这些函数在值发生改变时调用。如果新的值合法则返回true,否则返回false或者抛出异常。当他们简单地返回false时,将会抛出一个带有“Invalid reference state(非法引用状态)”消息的IllegalStateException异常。

<!--[if !supportLists]-->·         <!--[endif]-->They support watchers which are Agents. When the value of a watched reference changes, the Agent is notified. For more detail, see the "Agents" section.

他们都支持一种被称作为监视器的Agents。当被监视的引用的值发生改变时,Agent会被告知。更多细节可以参考章节"Agents"。

The table below summarizes some of the differences between the four reference types and the functions used to create and modify them. Each of the functions in the table below are described later.

 

下表总结了四种引用类型的不同的和用于创建并更新他们的函数。表中所列的每一个函数都会在接下来的章节中予以阐述。

 

 

Var

Ref

Atom

Agent

Purpose

synchronous changes
to a single, thread-local value

同步更改单个的线程内部的值

synchronous, coordinated changes
to one or more values

同步并且协调地改变一到多个值

synchronous changes
to a single value

同步改变单个值

asynchronous changes
to a single value

异步改变单个值

To create

(def name initial-value)

(ref initial-value)

(atom initial-value)

(agent initial-value)

To modify

(def name new-value) 
sets new root value


(alter-var-root
(var name) update-fn args) 
atomically sets new root value


(set! name new-value) 
sets new, thread-local value inside a
 binding form

(ref-set ref new-value) 
must be inside a
 dosync 


(alter ref 
update-fn arguments) 
must be inside a
 dosync 


(commute ref 
update-fn arguments) 
must be inside a
 dosync

(reset! atom new-value) 


(compare-and-set! atom current-value new-value) 


(swap! atom 
update-fn arguments)

(send agent 
update-fn arguments) 


(send-off agent 
update-fn arguments)

Vars

Vars are references that can have a root binding that is shared by all threads and can have a different value in each thread (thread-local).

Vars引用类型可以拥有供所有线程共享的一个root binding,并且可以在每个线程内部持有一个不同的值。

To create a Var and give it a root binding:

(def name value)

Providing a value is optional. If none is given then the Var is said to be "unbound". The same form is used to change the root binding of an existing Var.

值是可选的。如果没有给定值,则Var被当做是为绑定的。可以使用该表达式来改变一个已有Varroot binding,既:(def name value)

There are two ways to create a thread-local binding for an existing Var:

有两种方式给一个已有Var创建一个线程本地绑定:

(binding [name expression] body)

(set! name expression) ; inside a binding that bound the same name

Use of the binding macro was described earlier. The following example demonstrates using it in conjunction with the set! special form. That changes the thread-local value of a Var that was bound to a thread-local value by the binding macro.

 

(def v 1)

 

(defn change-it []

  (println "2) v =" v) ; -> 1

 

  (def v 2) ; changes root value

  (println "3) v =" v) ; -> 2

 

  (binding [v 3] ; binds a thread-local value

    (println "4) v =" v) ; -> 3

 

    (set! v 4) ; changes thread-local value

    (println "5) v =" v)) ; -> 4

 

  (println "6) v =" v)) ; thread-local value is gone now -> 2

 

(println "1) v =" v) ; -> 1

 

(let [thread (Thread. #(change-it))]

  (.start thread)

  (.join thread)) ; wait for thread to finish

 

(println "7) v =" v) ; -> 2

The use of Vars is often frowned upon because changes to their values are not coordinated across threads. For example, a thread A could use the root value of a Var and then later discover that another thread B changed that value before thread A finished executing.

使用var往往是令人皱眉, 因为线程之间对于同一个

______________________________________________________________________________

有待完成

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics