Clojure基础

最近看了一段clojure,下面是从书上摘下来的一下语言基础的精华部分

;函数的基本形式

(defn average
[numbers]
(/ (apply + numbers) (count numbers)))

(average [60 80 100 400])
(read-string "42")
(read-string "(+ 1 2)")
(pr-str [1 2 3])
(read-string "[1 2 3]")
"hello there"
(class \c)

;;创建一份hashmap包含两个键值对

(def person {:name "Sandra Cruz"
:city "Protland, ME"})
(:city person)
person
(:user/location person)
(def x 1)
x

;定义变量

(def x "hello")
*ns*
String
Integer
java.util.List
java.net.Socket
filter
x

;quote阻止求值,‘x是其简便形式

(quote x)
‘x

;fn是依次行定义,所以只能定义的同时使用,不能分开使用,可以再使用def定义别名这样就可以多次使用了

(def strange-adder (fn adder-self-reference
([x] (adder-self-reference x 1))
([x y] (+ x y))))
(strange-adder 10)
;defn=(def (fn ))
(defn adder-self-reference1
([x] (adder-self-reference1 x 1))
([x y] (+ x y)))
(adder-self-reference1 10)
(adder-self-reference1 10 50)

;可变参函数,x是一个固定参数,剩下其余的参数都被解构到rest中

(defn concat-rest
[x & rest]
(apply str (butlast rest)))

(concat-rest 0 1 2 3 4)

;fn定义后立即需要传入参数进行运算

((fn [x y] (Math/pow x y)) 2 10)

;使用#定义匿名函数

(#(Math/pow %1 %2) 2 10)

;匿名函数不隐含do,需要手工指定do

(#(do (println (str %1 \^ %2))
(Math/pow %1 %2)) 2 10)

;条件判断,第一个表达式是true的话,整个if就是第二个表达式的值,否则为第三个。任何非nil、非false的值都位true

(if (< 2 1) 2 1)

(defn countdown
[x]
(if (zero? x)
:blastoff!
(do (println x)
(recur (dec x)))))
(countdown 0)
(countdown 5)

;循环,recur能够在不消耗堆栈空间的情况下把程序执行转到离本地上下文最近的loop去

(loop [x 5];x=5
(if (neg? x) ;if x<0
x ;return x
(recur (dec x)))) ;esle loop(x-1)

;高阶函数map,将函数作用在集合上,返回一个序列

(map clojure.string/lower-case ["Java" "Imperative" "Weeping"
"Clojure" "Learning" "Peace"])
(map * [1 2 3 4] [5 6 7 8])

;高阶函数reduce 把集合应用在一个函数而产生单个值(归约)

(reduce max [0 -3 10 48])
(reduce + 50 [1 2 3 4])

(reduce
(fn [m v] (assoc m v (* v v)))
{}
[1 2 3 4])

;偏函数,把函数的一部分参数传给一个函数,创建一个新函数,这个函数所需参数就是剩下的那部分参数
;Clojure使用partial提供偏函数

(def only-strings (partial filter string?))
(only-strings ["a" "b" 1 2 3])

;使用函数组合重写上面的函数,clojure使用comp来实现函数组合
;comp接受任意数量的函数,comp接收的参数与最后一个函数的参数个数相等,一次从最后一个函数往前调用,前一个函数的返回值是后一个函数的参数,如果不能作为后一个函数的参数,则会报错
;例,返回给定数字列表的所有数字总和的负数字符串形式

(defn negated-sum-str
[& numbers]
(str (- (apply + numbers))))
(negated-sum-str 10 12 3.4)

;函数组合的形式

(def negated-sum-str (comp str - +))
(negated-sum-str 10 12 3.4)

;编写高阶函数
;编写一个高阶函数。它返回某个给定数字与它的参数的和

(defn adder
[n]
(fn [x] (+ n x)))
((adder 5) 18)

;编写一个高阶函数,它接受一个函数作为参数,同时返回一个函数,返回函数的作用是返回接受的函数的返回值的2倍

(defn doubler
[f]
(fn [& args]
(* 2 (apply f args))))
((doubler +) 1 2 3)

;可以使用别名简化

(def double+ (doubler +))
(double+ 1 2 3)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;日志系统;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;定义输入转接
(defn print-logger
[Writer];接收实现java.io.Writer接口的类实例
#(binding [*out* Writer];*out*默认绑定到标准输出,这里重新绑定到我们的Writer
(println %)));把要打印的消息,用println写入到*out*(已经替换成了Writer)
;标准输出
(def *out*-logger (print-logger *out*))
(*out*-logger "hello")
;内存buffer
(def writer (java.io.StringWriter.))
(def retained-logger (print-logger writer))
(retained-logger "hello")
;打印到文件
(require ‘clojure.java.io);require加载命名空间,可以起别名(require ‘clojure.java.io :as jio)
(defn file-logger
[file]
#(with-open [f (clojure.java.io/writer file :append true)];flie以追加模式打开,并把这个writer局部命名为f;with-open能够保证f在with-open结束的时候被关闭
((print-logger f) %)))

(def log->file (file-logger "/home//breezeli/Document/messages.log"));不指定目录的话用light table就找不到存到哪个目录去了
(log->file "hello")

;记录到多处的日志串接,高阶函数
(defn mutli-logger
[& logger-fns];任意数量参数
#(doseq [f logger-fns] (f %)));dosep遍历

(def log (mutli-logger
(print-logger *out*)
(file-logger "/home//breezeli/Document/messages.log")))
(log "hello again")

;每条日志前面加时间戳
(defn timestamped-logger
[logger]
#(logger (format "[%1$tY-%1$tm-%1$te %1$tH:%1$tM:%1$tS] %2$s"(java.util.Date.) %)))

(def log-timestamped (timestamped-logger
(mutli-logger
(print-logger *out*)
(file-logger "/home//breezeli/Document/messages.log"))))
(log-timestamped "goodbye,now")

;;;;;;;;;;;;;;;END;;;;;;;;;;;;;;;;;;;

;没有副作用且调用成本很高的纯函数可以内存化加快处理速度,clojure使用memoize实现内存化

(defn prime?
[n]
(cond
(== 1 n) false
(== 2 n) true
(even? n) false
:else (->> (range 3 (inc (Math/sqrt n)) 2)
(filter #(zero? (rem n %)))
empty?)));检测给定数字是不是素数
(time (prime? 1125899906842679))
(let [m-prime? (memoize prime?)]
(time (m-prime? 1125899906842679))
(time (m-prime? 1125899906842679)))

;map、vector、set和列表是Clojure提供的基本数据解构

‘(a b :name 12.5) ;;列表
[‘a ‘b :name 12.5] ;;vector
{:name "Chas" :age 31} ;;map
#{1 2 3} ;;set

;Clojure中所有的数据结构都实现了Collection抽象
;Collection的提供一下核心的集合函数
;conj添加一个元素到集合,保证对于所有的集合类型,都会高效地把元素添加到列表的第一个位置,因为如果添加在最后的话需要遍历列表,无法保证高效
;seq获取集合的顺序视图
;into建立在conj和seq之上
;count获取集合的元素个数
;empty获取一个跟所提供集合类型一样的空集合
;=判断两个或多个集合是否相等
;sequence系列,通常都被叫做“seq”,除了支持Collection提供的函数外还支持
;seq返回给传入参数的一个序列
(seq "Clojure")
;first、rest、next提供遍历序列的方法
(first "Clojure")
(rest "Clojure")
(next "Clojure") ;如果操作的结果是空,rest始终返回一个空序列,next返回nil,这是rest和next唯一的区别
;lazy-seq创建一个内容是一个表达式结果的惰性序列

时间: 2024-10-15 08:27:42

Clojure基础的相关文章

Clojure基础课程2-Clojure中的数据长啥样?

本文来自网易云社区 作者:李诺 " Clojure is elegant and pragmatic; it helps me focus more on solving business problems." 不同于Java这类静态语言, Clojure是动态语言,动态类型意味着这些类型会在代码运行时由Clojure动态的推导出来,编译时不作任何限制. user=> (defn f1 [a b] (+ "1" 2))#'user/f1 user=> (

clojure基础入门(一)

最近在看storm的源码,就学习分享下clojure语法. 阅读目录: 概述 变量 运算符 流程控制 总结 概述 clojure是一种运行在JVM上的Lisp方言,属于函数式编程范式,它和java可以方便的互相调用,这样开发的程序可以很好的结合java和clojure的优点(storm),这跟Net中C#和F#的角色一样. 安装java1.6以上的JDK,下载地址. 下载clojure的环境 包,下载地址. 解压后用命令行进入到clojure目录下,输入下面命令进入REPL命令行交互界面: ja

Clojure 学习笔记 1

Clojure 是一门运行在 JVM 上的 Lisp 方言.我的学习方式是通过看官网的Getting Started. Mac OS 下配置开发环境 用 homebrew 先安装 Java: brew install java 然后安装 Clojure 的 REPL 解释器: brew install clojure 暂时只安装了这么多,没有安装 Leiningen 和 Boot. 字面值(Literals) Clojure 有下面几种数据类型: ;; 数字类型 42 ; Long - 64 b

巧用Scrum与Kanban

本文来自网易云社区 文\屈鹏飞 在互联网行业的项目管理实践中,敏捷和精益一直是大家所提倡的思想,其中Scrum和Kanban方法作为即敏捷又精益的典型代表,许多PM都在研究,笔者近期也在学习和实施Scrum和Kanban方法,有些感触拿出来与大家一同分享. Kanban方法最初起源于丰田的JIT(Just In Time),之后作为一种高效管理软件开发流程的技术和思想应用于互联网行业.Kanban方法以价值流动为核心,不断发现团队中的瓶颈工序,进行改进,使价值流动更加顺畅和快速. Scrum源自

java web 开发三剑客 -------电子书

Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知Internet的目的是让各个net交互.所以,Internet实质上是将世界上各个国家.各个网络运营商的多个网络相互连接构成的一个全球范围内的统一网,使各个网络之间能够相互到达.各个国家和运营商构建网络采用的底层技术和实现可能各不相同,但只要采用统一的上层协议(TCP/IP)就可以通过Internet

【转】《从入门到精通云服务器》第六讲—OpenStack基础

前五期的<从入门到精通云服务器>受到了广泛好评,收到留言,有很多读者对云计算相关的技术非常感兴趣.应观众要求,我们这期要安利一条纯技术内容.准备好瓜子.花生,随小编一起进入OpenStack 基础知识大讲堂吧. 了解OpenStack OpenStack 是最火的开源软件之一,活跃度呈指数级别上升:它是一组开源项目,诞生之初是由两个项目组成,目前十几个项目:它是一个云操作系统,OpenStack is a cloud operating system that … OpenStack 管理的资

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

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

这技术太纯了|5分钟学会OpenStack 基础知识(转)

原文地址:http://mt.sohu.com/20160511/n448800357.shtml ——<从入门到精通云服务器>第六讲 前五期的<从入门到精通云服务器>受到了广泛好评,收到留言,有很多读者对云计算相关的技术非常感兴趣.应观众要求,我们这期要安利一条纯技术内容.准备好瓜子.花生,随小编一起进入OpenStack 基础知识大讲堂吧. 了解OpenStack OpenStack 是最火的开源软件之一,活跃度呈指数级别上升:它是一组开源项目,诞生之初是由两个项目组成,目前十

大数据架构师基础:hadoop家族,Cloudera产品系列等各种技术

大数据我们都知道hadoop,可是还会各种各样的技术进入我们的视野:Spark,Storm,impala,让我们都反映不过来.为了能够更好的架构大数据项目,这里整理一下,供技术人员,项目经理,架构师选择合适的技术,了解大数据各种技术之间的关系,选择合适的语言. 我们可以带着下面问题来阅读本文章: 1.hadoop都包含什么技术 2.Cloudera公司与hadoop的关系是什么,都有什么产品,产品有什么特性 3. Spark与hadoop的关联是什么? 4. Storm与hadoop的关联是什么