Clojure基础语法学习笔记(一)

本文介绍了Clojure编程语言的学习资源,包括实践性的课程和入门书籍。内容涵盖注释、命名空间、数据类型(如数字、字符串、字符、关键字和布尔值)以及数据结构(如列表、向量、集合和映射)。此外,还讨论了函数定义、局部变量绑定、条件判断以及Linux环境下安装lein和使用git进行项目管理的基本知识。
摘要由CSDN通过智能技术生成

首先推荐两个目前正在学的免费学习资源:

Functional programming in Clojure

Clojure for the Brave and True

都是英文的,第一个是边学边练的形式,很容易测试自己是否真的学懂了,在实践中也能学到更多的东西;第二个是一本Clojure的入门书籍,第二章介绍了Emacs的安装配置以及一些常用的快捷键,很适合作为新手入门教程。

一、注释和命名空间

目前学到的就两种:

; 为单行注释

#_ 可以注释掉之后的一个完整形,即#_后面第一个括号里面的内容

(ns namespace) ;改变命名空间后可以直接用该空间定义的函数变量等

命名空间用-,而对应的实际文件名用下划线_
user=> (use example.hello) ;使用use时,在后面的namespace前需要加单引号,否则会报错
java.lang.ClassNotFoundException: example.hello (NO_SOURCE_FILE:1)

(use 'clojure.repl)
(doc +) ;可以查看函数的说明
(user/clojuredocs function)
;to see some examples for function. This should work for most of the built-in functions.

二、数据类型

数值Numbers:11 2/3 3.2 整数 分数 浮点数等

运算符 + - * / mod ;mod返回两数相除的余数
逻辑 not = == >= <= > <
(== 42  42) ;=> true
(== 5.0  5) ;=> true
(=  5.0  5) ;=> false ! 即==要求值相等就行,=要求类型也一致,条件更严格

字符串Strings:"hello" "abc"用双引号表示

字符Characters:\x \b \? \√  用反斜杠表示特定字符

关键字Keywords::a :b :keyword 用英文的冒号开头表示

布尔值Booleans: true false nil 均为小写,nil表示为空,逻辑判断上是属于false的,但是跟false又有一些差别

(boolean ) ;返回true或false
(and true)                      ;=> true
(and true true true)            ;=> true
(and true true true true false) ;=> false
(and)                           ;=> true
;返回第一个非true值(nil或者false),或最后一个值
(or false false false false true) ;=> true
(or false false false)            ;=> false
(or)                              ;=> nil
(not true)        ;=> false
(not false)       ;=> true
对于booleans, and, or 和 not 均接受非布尔值作为参数.

(记住false 、nil 逻辑上都是false,除此之外的其他任何东西逻辑上都是true.)

三、数据结构

似乎初步区分为Collections集合和Sequences序列两大类,Lists,Vectors,Sets,Maps等都属于Collections,很多操作符也都是通用的(还在学习中,对这块认知还不是很清晰)

列表Lists:(1 2 3)

数组Vectors:[1 2 3]

集合Sets:#{1 2 3} 集合特点是元素是唯一的,不会有重复

集合Sets的字面量表示方法:#{an-elem another-elem ...}

(set ["^^" "^^" "^__*__^"]) ;=> #{"^__*__^" "^^"}
(set [1 2 3 1 1 1 3 3 2 1]) ;=> #{1 2 3}

contains? 用来测试集合是否包含一个值
(conj set elem) 在集合中加入一个元素
(disj set elem)  在集合中移除一个元素
(clojure.set/union set1 set2 ...) 合并多个集合
(clojure.set/union #{1 2} #{2 3} #{1 2 3 4} #{7 8}) ;=> #{1 2 3 4 7 8}
(apply clojure.set/union [#{1 2} #{5} #{7 8}])      ;=> #{1 2 5 7 8}

字典Maps:{:a 1 :b 2 :c 3} {"foo" 42, "bar" 666} {"mehmeh" (+ 2 5) "rupatipor" "ropopo"}

在Maps里你需要分清楚key和keyword,map里面成对出现的第一个是key,key常用keyword关键字来作为key,但是key也可以不是关键字而是其他类型
;关键字keyword是以":"开头的字符,如 :title  :authors

;关键字可以像函数一样用来索引查找关键字对应的值

如(:a {:a 1 :b 2 :c 3} ) ;=> 1

序列Sequences
(seq collection)  ;把集合转变为序列
(first sequence) ;返回序列中第一个元素
(rest sequence) ;返回序列中第一个元素外的其余元素
(cons item sequence) ;返回一个新序列,item是整个序列的第一个元素,sequence是剩下的其余元素

get的用法:

(get ["a" "b" "c"] 15) ;=> nil
;超出index范围时不会报错而是返回nil,中间分隔符可以是空格也可以是",",第一个元素index是从0开始的,如想要“a“需要get 0

 对maps用get,把后面的index序号替换为key:
(let [ages {"Juhana" 3
            "Ilmari" 42
            "King of All Cosmos" -6}]
  (get ages "King of All Cosmos"))
;=> -6


;vectors是不可变的,你只能创建新的vector
(conj [1 2 3] 4)          ;=> [1 2 3 4]

;assoc 有的替换,没有的新增
(assoc [1 2 3 4] 2 "foo") ;=> [1 2 "foo" 4] 这里把3替换成了”foo“
(assoc {:a 1} :b 2) ;=> {:b 2, :a 1}
(assoc {:a 1} :a 2) ;=> {:a 2}

;index: 0 1 2                0   1   2
(assoc [3 2 1] 1 "~o~") ;=> [3 "~o~" 1]

一些常用到的函数:

(str "Hello" 886 "!") ;连接字符串

(interpose ":" [1 2 3])        ;=> (1 ":" 2 ":" 3)
(interpose " and " ["a", "b"]) ;=> ("a" " and " "b")
(interpose ", " [])            ;=> ()
(apply str (interpose " and " ["a", "b"])) ;=> "a and b"

(count [1 2 3]) ;=> 3
(count {:name "China Miéville", :birth-year 1972}) => 2 ;注意到字典maps里一对算一个元素
(count ":)") => 2

(filter pos? [-4 6 -2 7 -8 3]) ;filter返回一个指示符为true的序列
;=>       (      6         7          3  )
; value    -4    6    -2   7     -8   3
; pos?   false true false true false true
(filter (fn [x] (> (count x) 2)) ["ff" "f" "ffffff" "fff"])
;=> ("ffffff" "fff")

(take 20 (cycle ["foo" "bar"])) ;,cycle是虚幻,take取循环的前20次
(get "Clojure" 2) ;=> \o
(repeat 5 "*") ;=> ("*" "*" "*" "*" "*")
(repeat 3 "~o~") ;=> ("~o~" "~o~" "~o~")

一些指示符:

(number? n) returns true if n is a number.
(empty? coll) returns true if coll is empty.
(list? coll) and (vector? coll) test if coll is a list or a vector.
(count coll) returns the length of a list or a vector.
(contains? {"a" 1} "a")   ;=> true
(contains? {"a" 1} 1)     ;=> false ;注意到contains?用于字典maps时,只有包含key才返回true,并不匹配值
(contains? {"a" nil} "a") ;=> true
(contains? cities :title) ;=> true
(contains? cities :name)  ;=> false

有点烧脑子的函数:

 (map function collection)
;map有两个参数,第一个是函数,第二个是一个集合序列
;map会对集合中的每一个元素应用这个函数,并将求值后的结果返回成一个序列
(apply function a-seq)
;apply有两个参数,第一个是函数,第二个是序列,apply会对序列中的每一个值应用这个函数
;apply和map有什么区别,光看描述感觉两者很像,简单来说map返回的还是一个序列,apply则不是
(apply concat [["China Miéville"] ["Octavia E. Butler"]])
;=> (concat ["China Miéville"] ["Octavia E. Butler"])
;=> ("China Miéville" "Octavia E. Butler")


;(mapv) 和(filterv), map和filter返回值为数组Vectors而不是序列的另一个版本.

四、定义函数

(defn square [x]
  "square a number"
  ( * x x))
;[ ]内的是参数,“ ”内描述函数功能,函数的返回值为最后一个表达式

let的用法:
(defn hypotenuse [x y]
  (let [xx (* x x)
        yy (* y y)]
    (Math/sqrt (+ xx yy))))
(let [name1 value1
      name2 value2
      ...]
  (expression1)
  (expression2)
  ...)
;let提供本地变量绑定,仅在let句式内生效
;let绑定的变量可以是在let里才刚刚声明的变量,但是有先后顺序的要求,即可以是a=1,b=a+1,但不能是a=b+1,b=1
(let [[x y z] [1 2 3 4 5 6]]
  (str x y z))
;=> "123"
;let另一种绑定的对应方式

(defn sum-pairs [first-pair second-pair]
  [(+ (first  first-pair) (first  second-pair))
   (+ (second first-pair) (second second-pair))])

(defn sum-pairs [[x1 y1] [x2 y2]]
  [(+ x1 x2) (+ y1 y2)])

(def x 1) ;绑定全局变量和值或函数

(if 判断条件 为真执行 为假执行) ;if后面的为判断条件,如果true执行第一个表达式,如果false执行第二个


(cond
  condition1 true1
  condition2 true2
  condition3 true3
  :else true4)  ;cond用于分情况执行,如果condition1条件为false则跳到condition2,如果123都不是那么执行:else后面的

五、其他

linux安装lein用到的一些命令:
cd ~
mkdir bin
export PATH=$PATH:~/bin
source ~/.bashrc
chmod +x ~/bin/lein

lein常用命令:
lein midje  :autotest  运行midje测试,在后面加  :autotest 可以在每次保存变更后自动运行
lein repl      打开Clojure repl循环
lein new     创建一个新的Clojure项目

lein help <command> 查找帮助

关于lein midje是如何测试的,是通过申明一系列的facts事实,然后测试函数运行结果与预期值是否相符

(facts "square"
  (square 2) => 4
  (square 3) => 9)

git常用命令:
git clone +链接 克隆文件到本地
git commit -a -m "message goes here" 把你的改动写入git关系,并在终端汇总显示你的改动
git push 上传你之前的改动到github需要账户及密码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值