
Clojure
文章平均质量分 50
zh2qiang
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
Programming Clojure学习笔记——探索Clojure
2.1 形式形式Clojure代码即数据。Clojure程序由读者(readers)和形式(forms)组成。当你运行Clojure程序时,读者读入形式并将之转换为Clojure数据结构。然后Clojure编译并执行该数据结构。以下为Clojure形式:Form Example(s)Boolean true, falseCharacter \aKey原创 2011-12-17 18:34:27 · 2704 阅读 · 0 评论 -
Programming Clojure学习笔记——使用序列统一数据
4.4 Clojure使Java可序列化1. 序列访问Java集合集合可以像序列一样操作称为可序列数组可序列user=> (first (.getBytes "hello"))104Hashtable和Map也可序列user=> (first (System/getProperties))#Clojure自动将集合包装成序列,但不会自动将集合还原为它们原来的原创 2012-02-05 09:57:39 · 1352 阅读 · 0 评论 -
Programming Clojure学习笔记——函数编程
5.2 如何延迟函数编程大量使用递归定义,递归定义由两部分组成:(1) 基础,明确列出序列的一些元素(2) 归纳,提供规则利用序列元素,生成更多的元素Clojure中有多种方法实现递归:(1) 简单递归,使用函数调用自己实现归纳步(2) 尾部递归,只在函数末尾调用函数自己实现归纳步(3) 延迟序列,消除实际的递归,延后直到需要时再计算值在Clojure中,采用延原创 2012-02-05 10:48:22 · 1226 阅读 · 0 评论 -
Programming Clojure学习笔记——函数编程
5.3 进一步延迟通过组合已有的序列函数,可以找到不需要显式序列的更加延迟的办法。举例说明,解决如下问题:统计硬币投掷结果序列中,连续两次出现正面的次数,其中:h表示正面,:t表示反面。如:[:h :t :t :h :h :h]第4、5连续两次,第5、6连续两次,一共出现2次第一种计算方法:使用loop/recur实现方式:(defn count-heads-p原创 2012-02-05 10:49:27 · 770 阅读 · 0 评论 -
Programming Clojure学习笔记——并发
Clojure提供强大的并发库,由四个API组成,增强不同并发模型:引用(refs): 管理对共享状态的并发同步修改原子(atoms): 管理对共享状态的非并发同步修改代理(agents): 管理对共享状态的异步修改变量(vars): 管理线程本地状态6.1 锁的问题选择在什么上和在哪里加锁是一件很难的事。如果加锁出现问题,会带来一系列问题:(1) 线程之间竞争导致原创 2012-02-05 11:04:12 · 615 阅读 · 0 评论 -
Programming Clojure学习笔记——使用序列统一数据
4.5 调用特定结构函数Clojure包含一些专门针对列表lists,向量vectors,映射maps,结构structs和集合sets的函数1. 针对列表Lists的函数(peek coll) 获取列表第一个元素,(peek '(1 2 3)) 返回1(pop coll) 获取除第一个元素外的其他元素,(pop '(1 2 3))返回(2 3)说明:如果列表coll为空,则p原创 2012-02-05 10:20:36 · 1618 阅读 · 0 评论 -
Programming Clojure学习笔记——使用序列统一数据
seq是一种逻辑列表。可以通过序列来访问的集合被称为可序列4.1 一切皆序列每一个聚集数据结构都可以看作序列,序列有三个核心操作:1. 取序列的第一个元素:(first aseq)如果参数为空或nil则返回nil2. 取第一个元素后的所有元素:(rest aseq)如果没有,则返回空,而不是nil3.在序列的头部添加一个元素构成一个新的序列(cons e原创 2012-02-05 09:53:46 · 1060 阅读 · 0 评论 -
Programming Clojure学习笔记——并发
6.3 使用Atoms进行非并发同步修改原子(Atoms)是一种比引用轻量的同步机制。创建原子语法:(atom initial-state options?)这里的选项options与引用refs的选项一样示例:使用atom存贮当前曲目代替引用ref(def current-track (atom "Venus, the Bringer of Pease"))同样的原创 2012-02-05 11:06:02 · 661 阅读 · 0 评论 -
Programming Clojure学习笔记——并发
6.4 使用Agents进行异步更新类似引用,可以使用代理(agent)包装初始状态。(agent initial-state)如创建counter代理包装初始计数0:(def counter (agent 0))可以send一个函数到agent修改agent的状态,该函数不会立即执行,而是存放到线程池的send队列中,稍后执行:(send agent update-f原创 2012-02-05 11:07:05 · 793 阅读 · 0 评论 -
Programming Clojure学习笔记——宏
7.2 编写控制流宏实现unless功能,与if相反,条件不成立时执行unless后代码。先编写函数来实现:user=> (defn unless [expr form] (if expr nil form))验证一下,当表达式expr为false时正确执行user=> (unless false (println "this should print"))this sho原创 2012-02-05 11:15:09 · 1660 阅读 · 0 评论 -
Programming Clojure学习笔记——宏
7.1 什么时候使用宏使用宏的两个原则和一个例外:原则1:不要写宏。宏很复杂而且需要仔细考虑宏展开时间和编译时间的相互影响。如果你能用一个函数替代就不要用宏。原则2:只在当且仅当只有宏可以封装你的模式时才使用宏例外:如果相比等效的函数,宏能使你的调用者生活变得更简单,那就用吧原创 2012-02-05 11:14:33 · 764 阅读 · 0 评论 -
Programming Clojure学习笔记——宏
7.4 宏的分类Clojure的特殊形式通常只能通过宏来实现,满足使用宏的第二个原则,因此宏的第二个原则也称为特殊形式原则。特殊形式有一些特殊的功能:(1) 特殊形式提供了大部分基本的流控制结构,如if和recur等(2) 特殊形式提供了直接访问Java的途径(3) 命名的创建和绑定都是通过特殊形式,不管是通过def定义的变量,还是通过let创建一个词法绑定,或者是通过bind原创 2012-02-19 00:20:16 · 1312 阅读 · 0 评论 -
Programming Clojure学习笔记——宏
7.3 使宏简单化Clojure为宏作者提供的支持形式 描述foo# 在语法上被引号引起的区域内,创建一个以foo为前缀的唯一名称(gensym prefix?) 以可选的前缀prefix创建唯一名称(macroexpand form) 使用macroexpand-1递归展开form原创 2012-02-19 00:17:46 · 1641 阅读 · 0 评论 -
Programming Clojure学习笔记——多重方法
8.1 没有多重方法的生活假定Clojure没有提供print和println方法,打印任何对象,println比print方法多输出一个换行符。我们自己构建一个通用的打印机制。为了输出字符串,空,向量我们需要如下编写代码:(use '[clojure.contrib.str-utils:only(str-join)])(defn my-print-vector [ob](.w原创 2012-02-28 20:38:40 · 1044 阅读 · 0 评论 -
Programming Clojure学习笔记——多重方法
8.2 定义多重方法定义多重方法使用defmulti:(defmulti name dispatch-fn)name为多重方法的名字,Clojure将针对方法的参数调用dispatch-fn来选择多重方法的一个特定的方法(实现)。考虑前一节的my-print函数,它只有一个参数,即需要打印的东西,可以基于参数的类型选择特定的实现。因此dispatch-fn必须是一个能返回参数类原创 2012-02-28 20:39:30 · 1372 阅读 · 0 评论 -
Programming Clojure学习笔记——多重方法
8.5 何时使用多重方法从Clojure的几个开源项目可以看出:1. 多重方法使用极少2. 很多多重方法都是基于类型(class)来分发使用以下一个通用原则来决定创建函数很是多重方法:1. 如果一个函数分支基于一种或多种类型,使用多重方法2. 不管它是什么,当你发现它是类别,而又不是Java类或数据标签时,使用多重方法3. 使用多重方法时,必须能够在没有多重方法定义原创 2012-02-28 20:42:58 · 882 阅读 · 0 评论 -
Programming Clojure学习笔记——多重方法
8.3 超越简单的分发定义一个打印集合的方法实现:(use '[clojure.contrib.str-utils :only (str-join)])(defmethod my-print java.util.Collection [c] (.write *out* "(") (.write *out* (str-join " " c)) (.wr原创 2012-02-28 20:40:31 · 804 阅读 · 0 评论 -
Programming Clojure学习笔记——使用序列统一数据
4.2 使用序列库序列库函数可以分为以下四大类:1. 创建序列函数2. 过滤序列函数3. 序列谓词4. 序列转换函数这种分类很粗糙,由于序列不可改变,因此大部分序列函数都创建新的序列,一些序列函数既有过滤也有转换功能。1. 序列创建(1) (range start? end step?) 创建一个从start到end,步长为step的序列,start默认为0,s原创 2012-02-05 09:55:09 · 1244 阅读 · 0 评论 -
Programming Clojure学习笔记——使用序列统一数据
4.3 延迟和无限序列大部分Clojure序列都是延迟的,即元素值直到使用时才计算。使用延迟序列有如下好处:1. 推迟可能不需要的昂贵计算2. 可以处理内存中无法存储的大数据集3. 可以延迟I/O操作,直到真正需要时延迟序列是Clojure函数编程的关键。强迫序列(forcing sequences)强迫延迟序列计算出所有序列元素值可以使用doall函数来强迫计原创 2012-02-05 09:56:14 · 1124 阅读 · 0 评论 -
Programming Clojure学习笔记——并发
6.5 使用Vars管理线程本地状态当你调用def或defn创建一个动态变量时,只是创建了一个变量。当你传一个初始值给def时,该初始值就成了def创建变量的根绑定(root binding),如:(def foo 10)变量foo的根绑定被所有线程共享,验证如下:当前线程中user=> foo10新起的线程中user=> (.start (Thread. (f原创 2012-02-05 11:09:02 · 897 阅读 · 0 评论 -
Programming Clojure学习笔记——探索Clojure
2.2 读者宏(Reader Macros)读者宏是被前缀macro触发的特殊读者行为。最熟悉的读者宏是注释,它被分号(;)触发,特殊的读者行为是忽略分号开头的行。读者宏是长列表形式的缩写,被用来减少复杂度,使代码看起来更简洁。下面是读者宏列表:Reader Macro Example(s)Anonymous function #(.toUpperCas原创 2011-12-17 18:37:26 · 876 阅读 · 0 评论 -
Programming Clojure学习笔记——与Java一起工作
3.2 性能优化使用原始类型示例:第一种计算方法:user=> (defn sum-to [n] (loop [i 1 sum 0] (if ( (recur (inc i) (+ i sum)) sum)))#'user/sum-touser=> (dotimes [_ 5] (time (sum-to 10000))原创 2011-12-18 09:22:29 · 1198 阅读 · 0 评论 -
Programming Clojure学习笔记——与Java一起工作
3.3 使用Clojure创建和编译Java类Clojure的所有对象都实现了Java的特定接口:1. Clojure数据结构实现了Java集合接口2. Clojure函数实现了Runnable和Callable接口Clojure可以在需要时很方便地在磁盘上生成一次性的代理或类,使用必要的一些Java代码片段。创建Java代理在Clojure中,可以使用代理来扩展原创 2011-12-18 09:25:27 · 2764 阅读 · 0 评论 -
Programming Clojure学习笔记——前言
Clojure是一种JVM上运行的动态编程语言,具有一下特性:1. 优雅Clojure的精心设计让你可以只关注解决问题本身2. 是Lisp的一种实现,继承了Lisp的强大功能,但不被Lisp语言的限制3. 是一种函数编程语言Clojure的数据结构都是不可变的,并且绝大部分函数都没有副作用4. 简化了并行编程Clojure提供了多种可选的锁:软件事务性存贮,代理,原子和原创 2011-12-17 18:19:15 · 811 阅读 · 0 评论 -
Programming Clojure学习笔记——开始
1.2 Clojure编程快速开始Clojure的运行条件:(1) Java运行环境,JDK5.0及以上(2) Clojure包运行REPL(read-eval-print-loop):>set PATH=D:\Java\jdk1.5.0\BIN>set CLOJURE_HOME=G:\Downloads\Clojure\clojure-1.3.0>java -cp原创 2011-12-17 18:26:49 · 1330 阅读 · 0 评论 -
Programming Clojure学习笔记——开始
1.3 探究Clojure库Colujure代码都打包进库,每个库属于一个命名空间namespace,命名空间类似Java包。可以使用require来加载Clojure库:(require quoted-namespace-symbol):user=> (require 'examples.introduction)nil说明:前导单引号必须,它将库名引起来使用库中函数原创 2011-12-17 18:29:07 · 985 阅读 · 0 评论 -
Programming Clojure学习笔记——探索Clojure
2.3 函数在Clojure中,函数调用是一个列表,其第一个元素为函数名。如:user=> (str "hello" " " "world")"hello world"在Clojure中,函数名习惯用连字符(-)连接个部分,如clear-agent-errors。如果一个函数是谓语,那么它的名字习惯性以问号(?)结尾。如:user=> (string? "he原创 2011-12-17 18:52:18 · 1313 阅读 · 0 评论 -
Programming Clojure学习笔记——探索Clojure
2.4 变量(var)当你使用def和defn定义一个对象时,对象就存贮在变量中,如:user=> (def foo 10)#'user/foo定义变量foo,其值为10。说明:这里的对象可以是数,也可以是函数变量的初始值称为根绑定。使用var特殊形式可以直接获取变量而不是变量的值:(var a-symbol)示例:user=> (var foo原创 2011-12-17 18:54:51 · 854 阅读 · 0 评论 -
Programming Clojure学习笔记——与Java一起工作
3.1 调用JavaClojure提供了简单直接的语法调用Java代码:创建对象,调用方法,访问静态方法和属性。访问构造函数,方法和属性Clojure提供了new形式调用构造函数创建实例(new classname)下面的代码创建Ramdom对象,赋给rnd变量:user=> (def rnd (new java.util.Random))#'user/rnd原创 2011-12-17 19:08:05 · 3428 阅读 · 0 评论 -
Programming Clojure学习笔记——与Java一起工作
3.4 异常处理异常处理的目的:(1) 包装检查异常(2) 使用finally块清理非内存资源如文件或网络句柄(3) 响应问题:忽略异常,重新操作,转换异常为非异常结果简化异常处理在Clojure中,检查异常不是必须进行try..catch处理,如果不处理则直接忽略异常资源清理如果需要是否的资源有close方法,则可以使用with-open宏:(wit原创 2011-12-18 09:31:48 · 894 阅读 · 0 评论 -
Programming Clojure学习笔记——开始
1.1 为什么选择Clojure?1. Clojure是优雅的相对其他语言,实现相同的功能,Clojure程序更短。因此Clojure程序更加容易构建发布和维护。如以下分别为Java和Clojure实现判断字符串是否为空白字符串的函数:Java代码:public class StringUtils {public static boolean isBlank(String st原创 2011-12-17 18:22:49 · 1264 阅读 · 0 评论 -
Programming Clojure学习笔记——探索Clojure
2.5 流控制ifClojure的if计算第一个参数值,如果第一个参数值为true,则返回第二个参数值;如果为false,则返回nil或第三个参数值(如果有第三个参数)user=> (defn is-small? [number] (if (#'user/is-small?user=> (is-small? 50)"yes"user=>原创 2011-12-17 18:58:23 · 1330 阅读 · 0 评论 -
Programming Clojure学习笔记——探索Clojure
2.6 元数据在Clojure中,元数据(metadata) 是与对象逻辑值正交的数据。如person的firstname 和 lastname是普通旧数据。而person对象可以被序列化到XML文件的信息就是元数据。同样person对象被更改需要保存到数据库的信息也是元数据。可以使用with-meta给集合(collection)和符号(symbol)添加元数据:(with原创 2011-12-17 19:00:25 · 950 阅读 · 0 评论 -
Programming Clojure学习笔记——函数编程
5.1 函数编程概念1. 纯函数函数式程序由纯函数构成。纯函数没有副作用,它只依赖与函数参数,只能通过函数返回值影响函数外部。纯函数常常与不可变数据一起工作。如:(defn mystery [input] (if input data-1 data-2))如果data-1和data-2是可变的,则它们可能被外界改变,对相同的input参数,可能输出不同,这与纯函数的特原创 2012-02-05 10:47:28 · 949 阅读 · 0 评论 -
Programming Clojure学习笔记——函数编程
5.4 再谈递归相互递归:两个或两个以上函数之间互相调用。如:(declare my-odd? my-even?)(defn my-odd? [n] (if (= n 0) false (my-even? (dec n))))(defn my-even? [n] (if (= n 0) true原创 2012-02-05 10:50:15 · 794 阅读 · 0 评论 -
Programming Clojure学习笔记——并发
6.2 引用和软件事务存贮在Clojure中,大部分对象都是不可变的。当你真的需要可变数据时,你必须明确说明,如创建一个可变的引用指向可变对象:(ref initial-state)如:(def current-track (ref "Mars, the Bringer of War")) 定义引用current-trackref包装并保护它内部的状态,控制对它内部状态的访问。原创 2012-02-05 11:04:54 · 886 阅读 · 0 评论 -
Programming Clojure学习笔记——多重方法
8.4 创建非正式类别多重方法让你可以创建非正式类别。举例说明,考虑一个财务应用,处理活期存款帐户和储蓄存款账户。为帐户定义一个Clojure结构,通过tag为标识这两种账户:(ns examples.multimethods.account)(defstruct account :id :tag :balance)接下来创建两种不同的账户,由::Checking和::Sa原创 2012-02-28 20:41:23 · 1100 阅读 · 0 评论