在百度百科中是这么定义引用类型的:“引用类型 由类型的实际值引用(类似于指针)表示的数据类型。如果为某个变量分配一个引用类型,则该变量将引用(或“指向”)原始值。不创建任何副本。引用类型包括类、接口、委托和装箱值类型”。Clojure的引用类型也于此类似。由于在Clojure中,纯函数式的可谓德高望重,备受推崇,也就意味着要尽量少用或者不用那些具有副作用特性的代码。但对数据状态的更改难以避免,毕竟事物总是变化的,因此Clojure中专门定义了一种引用类型。
以下中英文互译内容参考自Clojure - Functional Programming for the JVM。
Reference types are mutable references to immutable data. There are four
references types in Clojure: Vars, Refs, Atoms and Agents. They have many things in common:
引用类型是非易变数据的可变引用。Clojure中有四种引用类型: Vars, Refs, Atoms 和 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被当做是为绑定的。可以使用该表达式来改变一个已有Var的root 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往往是令人皱眉, 因为线程之间对于同一个
______________________________________________________________________________
有待完成
分享到:
相关推荐
ClojureScript是一种基于Lisp的方言,它继承了Clojure的强大特性和简洁语法,与JavaScript高度兼容,同时又提供了更高级的抽象和元编程能力。 在使用Infamous:ClojureScript DSL之前,你需要在你的`project.clj`...
ClojureScript 是一种基于 Clojure 语言的方言,专为编写高效、可维护的 JavaScript 代码而设计。这个名为 "breakout" 的项目显然是一个使用 ClojureScript 开发的实验性应用,旨在探索并展示这种编程语言在游戏开发...
ClojureScript 是一种基于 Lisp 语法的编程语言,它是 Clojure 的一个方言,主要用于编写运行在浏览器中的 JavaScript 代码。ClojureScript 能够通过 Google Closure 编译器转换为高效的 JavaScript,从而利用 ...
ClojureScript 是一种基于Clojure语言的方言,专为编写浏览器端JavaScript代码而设计。它保留了Clojure的语法和特性,同时提供了与JavaScript无缝交互的能力,使得开发者可以利用Clojure的强大功能来构建现代Web应用...
ClojureScript是一种基于Clojure语言的JavaScript方言,由Rich Hickey设计,主要用于编写高性能、跨平台的Web应用。这个压缩包"clojurescript-examples-源码.rar"包含了丰富的ClojureScript源码示例,是学习和理解...
### 学习ClojureScript:掌握敏捷单页Web应用开发艺术 #### 标题与描述解析 《Learning ClojureScript》是一本专为希望学习ClojureScript语言的开发者准备的书籍,出版于2016年6月。本书旨在帮助读者掌握如何利用...
重图(Re-Graph)是基于ClojureScript和Clojure的GraphQL客户端库,它为开发者提供了在Clojure和ClojureScript环境中与GraphQL服务器交互的能力。GraphQL是一种查询语言,由Facebook开发,用于API的设计,使开发者...
这是一种基于Lisp的编程语言,它是Clojure的方言,专门用于编写JavaScript应用程序。Clojurescript编译成JavaScript后,可以在任何支持JavaScript的环境中运行,包括Web浏览器。通过使用Clojurescript,rss-painter...
《sqlingvo:SQL在Clojure与ClojureScript中的DSL之旅》 在现代软件开发中,数据库查询语言SQL(Structured Query Language)仍然是处理结构化数据不可或缺的工具。然而,SQL的语法与许多现代编程语言相比显得较为...
ClojureScript是Clojure的一个方言,主要用于编写JavaScript运行时的代码,它通过Google Closure Compiler进行编译,生成优化的JavaScript代码。ClojureScript保留了Clojure的核心特性,同时也解决了跨平台的问题,...
ClojureScript,作为Clojure语言的一个方言,是用于编写JavaScript应用的高级编程语言。它以其独特的语法、强大的函数式编程特性和对JavaScript的无缝集成,吸引了众多开发者。在本文中,我们将深入探讨一个名为...
ClojureScript是Clojure编程语言的一个方言,主要用于编写Web应用的前端代码。它结合了Clojure的强大功能和JavaScript的运行时环境,为开发者提供了丰富的库和工具生态系统。在ClojureScript中进行测试是确保代码...
2. **ClojureScript**: ClojureScript 是Clojure语言的一个方言,专门用于编写Web前端代码。它是基于Google的 Closure Tools编译的,能够生成高效的JavaScript代码。ClojureScript保留了Clojure的核心特性,如Lisp...
s-expressions,或符号表达式,是Lisp家族语言中的基本构建块,包括Clojure和ClojureScript。这个系统允许开发者对源代码进行结构化处理,为编写编译器、解析器或者语言工具提供了强大的支持。 ClojureScript是...
ClojureScript 是一种基于 Lisp 语法的编程语言,它是 Clojure 的一个方言,主要用于编写 JavaScript 运行时环境中的代码。这个"hello-clojurescript"项目是一个基础的入门教程,旨在帮助开发者快速理解...
而ClojureScript是Clojure的一个方言,用于编写JavaScript的源代码,通常用于前端开发。Flow Storm Debugger正是为这两种语言提供了强大的调试支持。 Flow Storm Debugger的独特之处在于其对Clojure调试生态的深入...
首先,了解ClojureScript:ClojureScript是Clojure的一个方言,专门用于编写JavaScript运行时的代码。它与Clojure语法相似,但编译目标是JavaScript,这使得它能够无缝集成到Web开发中,利用JavaScript的广泛生态。 ...
动手全栈Clojure 封闭反馈循环以学习项目规模的Clojure(脚本)动机Clojure(script)是现代的Lisp方言,通常是一种不错的编程语言。 它一直在倡导的一种哲学是拥有的,而则是珍贵的瑰宝(尤其是clojurescript中的热...
Clojure是一种基于Lisp的函数式编程语言,而ClojureScript是其在JavaScript上的方言,主要用于前端开发。结合这两种语言,advenjure实现了跨平台的能力,可以在服务器端和浏览器端无缝运行。 ### 1. Clojure语言...
ClojureScript 是一种基于 Lisp 语法的编程语言,它是 Clojure 的一个方言,设计用于编写高性能的客户端应用程序,尤其在浏览器环境中。JavaScript 是 Web 开发中的基石,它被广泛用于实现网页动态效果和与服务器...