专栏首页米扑专栏Clojure 学习入门(13)—— binding

Clojure 学习入门(13)—— binding

Clojure里面是不支持变量的。Binding跟变量有点像,但是在被赋值之前是不允许改的,包括:全局binding, 线程本地(thread local)binding, 以及函数内的本地binding, 以及一个表达式内部的binding。

def 这个special form 定义一个全局的 binding,并且你还可以给它一个”root value” ,这个root value在所有的线程里面都是可见的,除非你给它赋了一个线程本地的值.def。也可以用来改变一个已经存在的binding的root value —— 但是这是不被鼓励的,因为这会牺牲不可变数据所带来的好处。

函数的参数是只在这个函数内可见的本地binding。

let 这个special form 创建局限于一个 当前form的bindings. 它的第一个参数是一个vector, 里面包含名字-表达式的对子。表达式的值会被解析然后赋给左边的名字。这些binding可以在这个vector后面的表达式里面使用。这些binding还可以被多次赋值以改变它们的值,let命令剩下的参数是一些利用这个binding来进行计算的一些表达式。注意:如果这些表达式里面有调用别的函数,那么这个函数是无法利用let创建的这个binding的。

bindinglet 类似, 但是它创建的本地binding会暂时地覆盖已经存在的全局binding. 这个binding可以在创建这个binding的form以及这个form里面调用的函数里面都能看到。但是一旦跳出了这个binding 那么被覆盖的全局binding的值会回复到之前的状态。

从 Clojure 1.3开始, binding只能用在 动态变量(dynamic var)上面了. 下面的例子演示了怎么定一个dynamic var。另一个区别是let 是串行的赋值的, 所以后面的binding可以用前面binding的值, 而binding 是不行的.

要被用来定义成新的、本地线程的、用binding来定义的binding有它们自己的命名方式:她们以星号开始,以星号结束。在这篇文章里面你会看到:*command-line-args*,*agent*,*err*,*flush-on-newline*,*in*,*load-tests*,*ns*,*out*,*print-length*,*print-level* and*stack-trace-depth*.要使用这些binding的函数会被这些binding的值影响的。比如给*out*一个新的binding会改变println函数的输出终端。

下面的例子介绍了def,let 和binding的用法:

; clojure connect to mysql
; ithomer.net
; 2013.12.10

(ns myClojure.syntax.binding)

(def ^:dynamic v 1)         ; v is a global binding
 
(defn f1 []
  (println "f1: v =" v))    ; global binding of 1
 
(defn f2 []
  (println "f2: before let v =" v)       ; global binding
  (let [v 2]                             ; creates local binding v that shadows global one
    (println "f2: in let, v =" v)        ; local binding of 2
    (f1))                                ; of 1
  (println "f2: after let v =" v))       ; global binding of 1
 
(defn f3 []
  (println "f3: before binding v =" v)   ; global binding of 1
  (binding [v 3]                         ; same global binding with new, temporary value
    (println "f3: in binding, v =" v)    ; global binding of 3
    (f1))                                ; of 3
  (println "f3: after binding v =" v))   ; global binding of 1
 
(defn f4 []
 (def v 4)                               ; changes the value of the global binding
 (println "f4: after binding v =" v)     ; of 4
 (f1))                                   ; of 4
 
(f2)
(f3)
(f4)
(println "after calling f4, v =" v)      ; of 4

运行结果:

f2: before let v = 1
f2: in let, v = 2
f1: v = 1
f2: after let v = 1
f3: before binding v = 1
f3: in binding, v = 3
f1: v = 3
f3: after binding v = 1
f4: after binding v = 4
f1: v = 4
after calling f4, v = 4

参考推荐:

Clojure入门教程

Clojure 基本语法

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • __attribute__机制介绍

    __attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Att...

    阳光岛主
  • 米扑科技的开源项目:sitemap-php 自动生成网站地图

    米扑科技旗下的产品,近期正在做SEO网站优化,其中子需求之一是调研实现了网站地图(sitemap.xml)

    阳光岛主
  • C++程序员经常问的11个问题

    这篇文章收了好长时间,但还是觉得贴出来,作为收藏,在网上这样的浮躁环境,很少能认认真真地看这样长的文章,有时间我也要把《Effective C++》的读书笔记作...

    阳光岛主
  • 使用TensorFlow一步步进行目标检测(5)

    本教程进行到这一步,您选择了预训练的目标检测模型,转换现有数据集或创建自己的数据集并将其转换为TFRecord文件,修改模型配置文件,并开始训练模型。接下来,您...

    云水木石
  • 三位数字的域名776.cn以18.4万元被拍

    数字有其通用性强、好记忆的优点,因为适合在各个领域建站,也备受投资人和终端喜爱,从而在价值上也有明显的优势。近日一枚三位数字的域名776.cn以18...

    躲在树上的域小名
  • CentOs 安装 vscode

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    云雀叫了一整天
  • Google Brain:NMT训练成本太高?用大规模神经机器翻译架构分析给出解决方案

    编者按:十年前,Google Translate发布。当时,这项服务背后的核心算法还是基于短语的机器翻译。 而十年后的今天,更先进的神经网络机器翻译( Neur...

    AI研习社
  • 开发 | NMT训练成本太高?Google Brain用大规模神经机器翻译架构分析给出解决方案

    AI科技评论编者按:十年前,Google Translate发布。当时,这项服务背后的核心算法还是基于短语的机器翻译。 而十年后的今天,更先进的神经网络机器翻译...

    AI科技评论
  • ES6-简介

    envoke
  • 关于数据库锁的那些事

    锁对于传统数据库来说是非常重要的, 里面也掺杂各种权衡, 概念类较多, 本文只针对部分内容做了讲解.

    用户2825413

扫码关注云+社区

领取腾讯云代金券