关于Clojure的Var,我大概了解了70%

对于Colure提供的Var,Ref,Agent,Atom不是不好理解,关键是不知道用在哪里?

随着编写clojure代码数量的增加,对于var有了更深的了解。下面就分享一下,如果能帮助你更快地理解var,将会是令人开心的事情。

java的变量是真的变量,你可以随时改变,按你的思维”自然“的改变,你甚至不会去注意它。但是clolure是不变为主,它的var需要好好思考一番。

1、产生var

    (def x 5)
    (println x) -------------> 5
    ;就产生了一个var,这里需要注意的是(println x)中的x在环境中解析成它的值,也就是5,但是var本身也是一个对象,如果你要得到var本身,就要用: #‘x,但这有什么用呢?有些special form或者macro需要用到。比如:
    (var-set x 6),你第一次使用var-set,有很大的可能性会这样写,但实际上是错误的,正确的是:
    (var-set #‘x 6),这样写就对了,但是和上面的代码结合起来还是错的,错误提示会是:java.lang.IllegalStateException: Can‘t change/establish root binding of: x with set。

2、改变var的值

(def ^:dynamic x 5)

(binding [x 6]
    (var-set (var x) 8) ; (var x) 和 #‘x 等价
    x) ---------> 8
;修改var的条件,必须是声明为dynamic,而且必须在binding里面。

3、改变var这么麻烦,而且2的示例代码有毫无意义,到底有什么用呢?

(def ^:dynamic *shiro-respnse*)

(deftest cssesion-request
  (binding [*shiro-respnse* ((csession-app) (sample-request))]
    (is (get-in *shiro-respnse* [:cookies :JSESSIONID]))))

Clojure的macro: with-precision,就是一个例子。但是理解var最好的办法是:你觉得自己的某一段代码必须使用var,否则代码会非常不舒服。

到那个时候,你对于var的理解才会有本质的进步。

由于clojure的测试只有一个:is。用来测试跟在后面的form的结果是真。上面的代码3,为了测试csession-app的返回的response是否包含JSESSIONID,如果不用binding,那么is后面的form会非常长,而且必须用do来串联多个is。用binding之后代码就清爽多了。

但是这里用binding其实根本没有体现binding的作用,完全可以用let来替代。

我之所以用binding,是因为我总算找到一处可以在自己的代码中使用binding的机会,并且it works。

4、用可变的var写clojure代码。(这其实是反clojure模式的)

(defn factorial [x]
         (with-local-vars [acc 1, cnt x]
           (while (> @cnt 0)
             (var-set acc (* @acc @cnt))
             (var-set cnt (dec @cnt)))
           @acc))
           
;这段代码对于java程序员就很好理解了。

5、真正使用var的场景,来自clojure的源代码

(defmacro with-precision
  "Sets the precision and rounding mode to be used for BigDecimal operations.

  Usage: (with-precision 10 (/ 1M 3))
  or:    (with-precision 10 :rounding HALF_DOWN (/ 1M 3))

  The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN,
  HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP."
  {:added "1.0"}
  [precision & exprs]
    (let [[body rm] (if (= (first exprs) :rounding)
                      [(next (next exprs))
                       `((. java.math.RoundingMode ~(second exprs)))]
                      [exprs nil])]
      `(binding [*math-context* (java.math.MathContext. ~precision [email protected])]
         [email protected])))

这是一个macro,通过绑定环境,让代码得以正确的执行。那为什么这里不用let呢?你看代码的最后一行,你可以在你传入的body里面使用*match-context*,而且这个*match-context*是thread local的var,你在这块代码里面使用,不会干扰另外一块代码的*match-context*值。

时间: 2024-10-13 23:55:18

关于Clojure的Var,我大概了解了70%的相关文章

Clojure学习笔记(一)——介绍、安装和语法

什么是Clojure Clojure是一种动态的.强类型的.寄居在JVM上的语言. Clojure的特性: 函数式编程基础,包括一套性能可以和典型可变数据结构媲美的持久性数据结构 由JVM提供的成熟的.高效的运行时环境:所以Clojure可以使用Java类库,反之Clojure库也可以被Java使用 跟JVM/Java的互操作能力使得很多架构.运维方面的需求可以得到满足:Clojure代码可以像Java代码一样被打包,然后部署到任何Java应用可以部署的地方 一套提供并发.并行语义的机制:Clo

salt package manager (SPM)

salt package manager 简称SPM,使用man查看spm命令的使用方法,这一部分内容比较多,初浅的看了下文档,暂时先总结个大概,后续慢慢在探究一下细节,再进行补充. salt 的包管理主要包含以下3个部分, 关系如图示: (1)Packaging System  包组织系统:主要内容包含如何建立一个SPM Packages. 解析formula格式的目录结构: (2)Repo System  建立repo包仓库和相关信息    (3)Salt Master  如何安装.spm的

ddos 防御 - TCP 网络层防御

cron_ddos_tcp.sh 1#!/bin/sh  2   3   4 for kip in `netstat -an |grep -i ':80' |grep 'EST' | awk '{print $5}' | cut -d : -f 1 | sort | uniq -c | awk '{if($1 > 50 && $2 !~ /192\.168\.1\.19.|0\.0\.0\.0/) {print $2}}'`; do  5   6 echo $kip >>

微信发送模板消息代码示例

最近一个微信的项目里需要发送微信模板消息给卖家或者供应商等,微信开发其实也就按照微信的官方接口要求组装起来即可,下面简单介绍一下我的微信模板发送代码. 1.获取access token,至于access token是什么,大家可以自行微信接口文档看一下,这边不多说 获取access token我这边主要是用定时器没大概2分钟获取一次,每天获取的次数是100000次,用法如下: 1 #region 2 3 using System; 4 using System.Timers; 5 6 #endr

雅虎35条优化黄金守则

Excetional Performance 团队总结出了一系列可以提高网站速度的方法.可以分为 7大类 35条.包括内容 .服务器 . CSS . JavaScript .Cookie .图片 .移动应用 ,七部分. 一.内容部分 尽量减少 HTTP请求 减少 DNS查找 避免跳转 缓存 Ajxa 推迟加载 提前加载 减少 DOM元素数量 用域名划分页面内容 使 frame数量最少 避免 404错误 1.尽量减少 HTTP请求次数 终端用户响应的时间中,有 80%用于下载各项内容.这部分时间包

Yahoo! 35条网站性能优化建议

Yahoo! 35条网站性能优化建议 分类: 网站性能优化2014-03-08 17:18 212人阅读 评论(0) 收藏 举报 网站性能优化 Yahoo!的 Exceptional Performance团队为改善 Web性能带来最佳实践.他们为此进行了一系列的实验.开发了各种工具.写了大量的文章和博客并在各种会议上参与探讨.最佳实践的核心就是旨在提高网站性能.原版猛戳:Best Practices for Speeding Up Your Web Site, Excetional Perfo

【UI插件】简单的日历插件(下)—— 学习MVC思想

前言 我们上次写了一个简单的日历插件,但是只是一个半成品,而且做完后发现一些问题,于是我们今天尝试来解决这些问题 PS:距离上次貌似很久了 上次,我们大概遇到哪些问题呢: ① 既然想做一套UI库,那么就应该考虑其它UI库的接入问题 这个意思就是,我们的系统中所有UI插件应该有一些统一行为,我们如果希望统一为所有的插件加一点什么东西,需要有位置可加 这个意味着,可能我们所有的插件需要继承至一个抽象的UI类,并且该类提供了通用的几个事件点 ② 上次做的日历插件虽然说是简单,其耦合还是比较严重的(其实

Yahoo!团队:网站性能优化的35条黄金守则

Yahoo!的 Exceptional Performance团队为改善 Web性能带来最佳实践.他们为此进行了一系列的实验.开发了各种工具.写了大量的文章和博客并在各种会议上参与探讨.最佳实践的核心就是旨在提高网站性能.原版猛戳:Best Practices for Speeding Up Your Web Site, Excetional Performance 团队总结出了一系列可以提高网站速度的方法.可以分为 7大类 35条.包括内容 .服务器 . CSS . JavaScript .C

CentOS6.4 安装ldap

参考http://kinggoo.com/openldapinstallconf.htm 参考http://linux.it.net.cn/CentOS/server/set/2014/1203/9510.html 参考http://407711169.blog.51cto.com/6616996/1439944 参考http://linuxadmin.blog.51cto.com/2683824/1615515 参考http://ljl2013.blog.51cto.com/186072/13