Programming Clojure学习笔记——探索Clojure

本文介绍了Clojure编程中的变量使用、函数参数绑定与命名空间的概念,包括变量的根绑定、直接获取变量、绑定创建、非结构化访问及命名空间的切换与创建。详细解释了如何在Clojure环境中高效地管理和使用变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.4 变量(var)
当你使用def和defn定义一个对象时,对象就存贮在变量中,如:
user=> (def foo 10)
#'user/foo
定义变量foo,其值为10。

说明:这里的对象可以是数,也可以是函数

变量的初始值称为根绑定。

使用var特殊形式可以直接获取变量而不是变量的值:
(var a-symbol)
示例:
user=> (var foo)
#'user/foo

var有一个等价的读者宏#':
user=> #'foo
#'user/foo
二者返回值相同

绑定
函数调用时,传入参数值绑定到参数名称,函数参数绑定有一个词法作用域:仅在函数体范围内可见。
有一种特殊形式let可以创建一组词法绑定:
(let [bingdings*] exprs*)
其中bingdings在exprs中有效,let返回exprs最后一个表达式的值。如:
user=> (defn square-corners [bottom left size]
         (let [top (+ bottom size)
               right (+ left size)]
           [[bottom left] [top left] [top right] [bottom right]]))
#'user/square-corners
user=> (square-corners 1 1 2)
[[1 1] [3 1] [3 3] [1 3]]

非结构化
有时候我们需要访问结构体的部分数据,如访问作者的first-name,可以通过以下函数实现:
user=> (defn greet-author-1 [author]
                (println "Hello," (:first-name author)))
#'user/greet-author-1
user=> (greet-author-1 {:last-name "Vinge" :first-name "Vernor"})
Hello, Vernor
函数接受作者结构体并绑定到author参数,但函数只需要first-name。

通过非结构化,Clojure通过在绑定中嵌入向量或映射深入集合内部并只绑定需要的部分数据。如:
user=> (defn greet-author-2 [{fname :first-name}]
                (println "Hello," fname))
#'user/greet-author-2
user=> (greet-author-1 {:last-name "Vinge" :first-name "Vernor"})
Hello, Vernor

可以使用向量解构任意有序集合。如:
user=> (let [[x y] [1 2 3]] [x y])
[1 2]
表达式[x y]解构向量[1 2 3],绑定x到1,y到2

可以使用下划线(_)来忽略某个元素,如:
user=> (let [[_ _ z] [1 2 3]] z)
3
两个下划线表示忽略前两个元素,将z绑定到第三个元素3

在解构表达式中,:as语句:as后的变量绑定到整个结构:
user=> (let [[x y :as coords] [1 2 3 4 5 6]]
         (str "x: " x ", y: " y ", total dimensions " (count coords)))
"x: 1, y: 2, total dimensions 6"
将coords绑定到向量[1 2 3 4 5 6]

命名空间
在Clojure REPL中,user=>提示符表明当前处于user命名空间。
根绑定都在命名空间中,如:
user=> (def foo 10)
#'user/foo
Clojure解析变量foo时,使用当前命名空间user来限定它,如:
user=> (resolve 'foo)
#'user/foo

使用in-ns切换(如果没有则创建)命名空间:
(in-ns name)
创建并切换至myapp命名空间:
user=> (in-ns 'myapp)
#
myapp=>
当前的命名空间变为myapp,此时定义的任何东西都属于myapp,如:
myapp=> (def foo 11)
#'myapp/foo

当使用in-ns创建新的命名空间时,java.lang包自动引入到新的命名空间中,如:
myapp=> String
java.lang.String

使用下面语句引入Clojure核心函数到新命名空间:
myapp=> (clojure.core/use 'clojure.core)
因为没法直接使用use,所以需要加上前缀clojure.core。

使用java.lang包以外的类时,需要加上完整包名,如:
myapp=> java.io.File/separator
"\\"
如果不想麻烦,每次都使用类时都加上类的包名,可以使用import函数引入要使用的类:
(import '(package Class+))
引入后,就可以直接使用类名无需加包名前缀,如:
myapp=> (import '(java.io InputStream File))
java.io.File
myapp=> File/separator
"\\"
注意:import只针对Java类。

如果要使用其他命名空间的Clojure变量则需要使用全名称或使用use将其映射到当前命名空间,如:
myapp=> (use 'clojure.contrib.math)
myapp=> (round 1.7)
2
使用use时,可以加上:only选项只映射需要的变量:
myapp=> (use '[clojure.contrib.math :only (round)])
nil
myapp=> (round 1.2)
1
使用use时,可以加上:reload选项实时加载最新的库代码:
myapp=> (use :reload '[clojure.contrib.math :only (round)])

习惯使用us宏在源文件头一次性导入Java类和Clojure命名空间:
(ns name & references)
ns 宏将当前命名空间切换至name命名空间(如果需要则创建),references可以包含:import,:require和:use语句:
myapp=> (ns examples.exploring
                    (:use examples.utils clojure.contrib.str-utils)
                    (:import (java.io File)))
java.io.File
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值