Skip to main content
 Web开发网 » 操作系统 » linux系统

Clojure总结

2021年10月15日6720百度已收录

Leiningen

Clojure总结  Leiningen 第1张

将依赖项下载到本地并放置在适当的位置

启动REPL

Clojure总结  Leiningen 第2张

通过设置*print-length*的值,来配置打印器一次最多打印多少项。

Clojure总结  Leiningen 第3张

记录

Clojure总结  Leiningen 第4张

Clojure总结  Leiningen 第5张

Clojure总结  Leiningen 第6张

Clojure总结  Leiningen 第7张

Clojure总结  Leiningen 第8张

Clojure总结  Leiningen 第9张

匿名函数

Clojure总结  Leiningen 第10张

Clojure总结  Leiningen 第11张

Clojure总结  Leiningen 第12张

Clojure总结  Leiningen 第13张

其参数被命名为%1、%2,以此类推。对于第一个参数,可以使用%表示。

协议和数据类型● 协议(Protocol)作为Java接口的替代物,适于高性能的多态方法调度。

● 数据类型(Datatype)作为Java类的替代物,可用来创建抽象定义的实现,无论该抽象是由协议还是接口定义的。

一个变量的初始值被称为它的根绑定(root binding)

变量def defn、绑定Clojure总结  Leiningen 第14张

Clojure总结  Leiningen 第15张

绑定letClojure总结  Leiningen 第16张

这里的bindings会在随后的exprs中生效,此外,exprs中最后一个表达式的值,就会成为let的返回值。

Clojure总结  Leiningen 第17张

解构Clojure总结  Leiningen 第18张

Clojure总结  Leiningen 第19张

可以同时绑定整个容器与容器内的元素。在解构表达式内部,:as字句允许绑定整个闭合结构。

Clojure总结  Leiningen 第20张

Clojure总结  Leiningen 第21张

resolveClojure总结  Leiningen 第22张

resolve会返回在当前命名空间中,解析符号得到的变量或是类。

Clojure总结  Leiningen 第23张

in-ns来切换命名空间或创建新的命名空间

Clojure总结  Leiningen 第24张

requireClojure总结  Leiningen 第25张

Clojure总结  Leiningen 第26张

为了在当前命名空间中引入split别名,可以包含对split的命名空间clojure.string调用require,并用str用作其别名。

Clojure总结  Leiningen 第27张

referrefer将其下的所有名称映射到当前命名空间中

Clojure总结  Leiningen 第28张

Clojure总结  Leiningen 第29张

use函数把require和refer合并成了一个步骤

Clojure总结  Leiningen 第30张

Clojure总结  Leiningen 第31张

:reload在调用require或use时,使用:reload标记用来强制重新加载一个程序库。

Clojure总结  Leiningen 第32张

查找文档

Clojure总结  Leiningen 第33张

Clojure总结  Leiningen 第34张

使用repl库的source函数来查阅某个Clojure函数的源码

Clojure总结  Leiningen 第35张

形式

Clojure总结  Leiningen 第36张

比例(Ratio)类型

Clojure总结  Leiningen 第37张

使用quot和rem函数来获取整型的商和余数

Clojure总结  Leiningen 第38张

java

Clojure总结  Leiningen 第39张

Clojure总结  Leiningen 第40张

Clojure总结  Leiningen 第41张

Clojure总结  Leiningen 第42张

Clojure总结  Leiningen 第43张

toUpperCase前面的句点告知Clojure,应该将其视为一个Java方法,而非Clojure函数。

Clojure总结  Leiningen 第44张

读取器宏

Clojure总结  Leiningen 第45张

函数

Clojure总结  Leiningen 第46张

Clojure总结  Leiningen 第47张

Clojure总结  Leiningen 第48张

Clojure总结  Leiningen 第49张

在参数列表中包含一个&号,你就能创建一个具有可变元数的函数。Clojure会把所有剩余的参数都放进一个序列中,并绑定到&号后面的那个名称上。

Clojure总结  Leiningen 第50张

使用import把一个或者多个类名从Java包映射到当前命名空间中

Clojure总结  Leiningen 第51张

Clojure总结  Leiningen 第52张

Clojure总结  Leiningen 第53张

import仅用于Java类。

Clojure会自动导入java.lang。

ns

Clojure总结  Leiningen 第54张

ns宏将当前命名空间(可通过*ns*获取)设置为name,必要时还会创建这个命名空间。

references部分则可以包含:import、:require和:use。它们的工作方式与各自对应的同名函数类似。这样仅需要一个形式,就可以完成命名空间映射相关的所有设置。

Clojure总结  Leiningen 第55张

new

Clojure总结  Leiningen 第56张

Clojure总结  Leiningen 第57张

Javadoc

Clojure总结  Leiningen 第58张

分支结构与ifClojure的if会对其第一个参数进行求值。倘若结果逻辑为真,就返回对第二个参数求值的结果。

Clojure总结  Leiningen 第59张

Clojure总结  Leiningen 第60张

Clojure总结  Leiningen 第61张

if do

Clojure总结  Leiningen 第62张

do可以接受任意数量的形式,对这些形式逐个求值,并返回最后一个形式的求值结果。

do就是用来申明“注意,接下来会有副作用”的方式之一。

除了最后一个形式,do会把所有其他形式的返回值都给忽略掉,所以,这也就意味着对于那些被忽略掉的形式来说,必须具有某种副作用才有其存在的意义。

循环与loop/recur

Clojure总结  Leiningen 第63张

loop与let的工作方式颇为相似,首先建立绑定bindings,然后对expres求值。

不同的地方是,loop设置了一个循环点(recursion point),随后这个循环点将成为特殊形式recur返回目标。

Clojure总结  Leiningen 第64张

早先由Loop建立的绑定,会被recur重新绑定为新的值,并且控制程序流程返回到loop的顶端。

Clojure总结  Leiningen 第65张

首次进入时,loop 把 result 和一个空向量进行了绑定,并把 x 绑定为 5。由于 x不为零,recur随后对名称x和result再次进行了绑定。

● result被绑定至一个新的向量,该向量是通过连接早先的result和x得到的。

● x则被绑定为前一个x的递减结果。

接下来程序流回到了loop的顶端。

由于这一次x仍然不为零,循环继续,再次对result加以累积并递减x。最终,x递减为零,if终结了循环并返回result。

去掉 loop,能让 recur 递归至函数的起始位置。这就使得编写那种把整个主体都用作隐式循环的函数变得极为容易。

Clojure总结  Leiningen 第66张

meta

Clojure总结  Leiningen 第67张

Clojure总结  Leiningen 第68张

Clojure总结  Leiningen 第69张

Clojure总结  Leiningen 第70张

Clojure总结  Leiningen 第71张

因为元数据:tag实在是太常用了,可以使用其简化形式^Classname,它会被展开为^{:tag Classname}。

Clojure总结  Leiningen 第72张

在阅读函数定义时,如果发觉元数据会造成视觉混乱,也可以把它们放到最后。这得用到 defn 的一个变体,先是一或多个带括号的函数主体,随后紧接一个元数据映射表。

Clojure总结  Leiningen 第73张

序列 first

Clojure总结  Leiningen 第74张

序列 rest

Clojure总结  Leiningen 第75张

序列cons

Clojure总结  Leiningen 第76张

序列seq

Clojure总结  Leiningen 第77张

序列next

Clojure总结  Leiningen 第78张

(next aseq)等价于 (seq (rest aseq))

Clojure总结  Leiningen 第79张

对向量使用rest或cons时,得到的结果是一个序列,而非向量。

序列函数返回的总是序列。

sorted-set

Clojure总结  Leiningen 第80张

Clojure总结  Leiningen 第81张

sorted-map

Clojure总结  Leiningen 第82张

Clojure总结  Leiningen 第83张

conj

Clojure总结  Leiningen 第84张

Clojure总结  Leiningen 第85张

conj 会向容器添加一个或是多个元素

into

Clojure总结  Leiningen 第86张

Clojure总结  Leiningen 第87张

into 则会把容器中的所有元素添加至另一个容器。添加数据时,conj和into都会根据底层数据结构的特点选取最高效的插入点。

对于列表而言,conj和into会在其前端进行添加。

Clojure总结  Leiningen 第88张

对于向量,conj和into则会把元素添加至末尾。

Clojure总结  Leiningen 第89张

range生成一个从start开始到end结束的序列,每次的增量为step。

Clojure总结  Leiningen 第90张

范围包含了start,但并不包含end。没有指定的话,start默认为0,step默认为1。

Clojure总结  Leiningen 第91张

repeat

Clojure总结  Leiningen 第92张

repeat函数会重复n次元素x。

Clojure总结  Leiningen 第93张

iterate

Clojure总结  Leiningen 第94张

iterate起始于值x,并持续地对每个值应用函数f,以计算下一个值,直至永远。

Clojure总结  Leiningen 第95张

take

Clojure总结  Leiningen 第96张

take会返回一个包含了容器中前n项元素的惰性序列。

cyclecycle函数接受一个容器,并无限的对其进行循环。

Clojure总结  Leiningen 第97张

Clojure总结  Leiningen 第98张

interleaveinterleave函数接受多个容器作为参数,并产生一个新的容器,这个新容器会从每个参数容器中交错地提取元素,直至其中某个容器元素被耗尽。

Clojure总结  Leiningen 第99张

当其中的某个容器被耗尽时,interleave就会终止。

Clojure总结  Leiningen 第100张

interpose把输入序列中的每个元素用分隔符隔开,并作为新的序列返回。

Clojure总结  Leiningen 第101张

Clojure总结  Leiningen 第102张

join(apply str ...)

Clojure总结  Leiningen 第103张

Clojure总结  Leiningen 第104张

创建容器

Clojure总结  Leiningen 第105张

Clojure总结  Leiningen 第106张

set函数

Clojure总结  Leiningen 第107张

vecvec接受容器作为参数,而非可变的参数列表。

Clojure总结  Leiningen 第108张

filter

Clojure总结  Leiningen 第109张

Clojure总结  Leiningen 第110张

take-while

Clojure总结  Leiningen 第111张

Clojure总结  Leiningen 第112张

complementcomplement 会反转另一个函数的行为。

drop-while函数

Clojure总结  Leiningen 第113张

drop-while 从序列的起始位置开始,逐个丢弃元素,直至谓词判定为真,然后返回序列剩余的部分。

Clojure总结  Leiningen 第114张

split-at和split-with能把一个容器一分为二

Clojure总结  Leiningen 第115张

Clojure总结  Leiningen 第116张

所有take-、split-和drop-打头的函数,返回的都是惰性序列。

every?every?要求其他谓词对序列中的每个元素都必须判定为真。

Clojure总结  Leiningen 第117张

some

Clojure总结  Leiningen 第118张

只要有一个元素被谓词判定为非假,some就会返回这个值,如果没有任何元素符合,则some返回nil。

Clojure总结  Leiningen 第119张

注意,some没有以问号结尾。尽管总被当作谓词使用,但some并非谓词。

some 返回的是第一个符合项的值,而非 true。由于 even?本身就是一个谓词,所以当some与even?配对使用时,其间的差异并不明显。

映射函数map

Clojure总结  Leiningen 第120张

map接受一个源容器coll和一个函数f作为参数,并返回一个新的序列。该序列的所有元素,都是通过对coll中的每个元素调用f得到的。

Clojure总结  Leiningen 第121张

还可以传入多个容器给map。在这种情况下,f必须是一个多参函数。map会从每个容器分别取出一个值,作为参数来调用f,直到数量最少的那个容器被耗尽为止。

Clojure总结  Leiningen 第122张

归纳函数reduce

Clojure总结  Leiningen 第123张

其中f是一个接受两个参数的函数。reduce首先用coll的前两个元素作为参数来调用f,然后用得到的结果和第三个元素作为参数,继续调用f,以此类推。

Clojure总结  Leiningen 第124张

sort或sort-by对容器进行排序

Clojure总结  Leiningen 第125张

sort 会依据元素的自然顺序对容器进行排序,sort-by 则会对每个元素调用 a-fn,再依据得到的结果序列来进行排序。

Clojure总结  Leiningen 第126张

Clojure总结  Leiningen 第127张

列表解析(list comprehension)基于一个已存在的列表来创建新的列表。

解析式描述了结果列表必须满足的性质。

一个列表解析会包含以下内容。

● 输入列表。

● 输入列表中元素所对应的占位变量。

● 作用于元素的谓词。

● 一个输出形式,它负责基于那些满足谓词要求的列表元素来产生输出。

Clojure把列表解析的概念泛化为了序列解析(sequencecomprehension)。

Clojure总结  Leiningen 第128张

for 接受一个向量作为参数,该参数是由一系列 binding-form/coll-expr 和可选的filter-expr组成的,然后是依据表达式expr来产生结果序列。

Clojure总结  Leiningen 第129张

Clojure总结  Leiningen 第130张

Clojure总结  Leiningen 第131张

序列解析中,Clojure会从按照右到左的顺序,来遍历绑定表达式。由于在绑定形式中,rank列于file的右手边,所以rank会迭代的更快。

Clojure总结  Leiningen 第132张

doall强制求值

Clojure总结  Leiningen 第133张

doall迫使Clojure遍历序列中的元素,并把这些元素作为结果返回。

dorun

Clojure总结  Leiningen 第134张

dorun遍历容器中的元素,但它不会把穿过的元素保留在内存中。

dorun可以遍历那些超过了内存容许范围的超大容器。

Clojure总结  Leiningen 第135张

re-seq

Clojure总结  Leiningen 第136张

re-seq会把匹配结果暴露为一个不可变的序列。

Clojure总结  Leiningen 第137张

file-seq深度优先的遍历方式

Clojure总结  Leiningen 第138张

line-seq将Java的Reader以行的方式进行序化

Clojure总结  Leiningen 第139张

with-open

Clojure总结  Leiningen 第140张

xml-seq

Clojure总结  Leiningen 第141张

以序列的方式来查看树。

Clojure总结  Leiningen 第142张

列表函数peek和pop分别用于取出列表的第一个元素,和其余的那些元素。

Clojure总结  Leiningen 第143张

Clojure总结  Leiningen 第144张

peek等同于first,但pop则与rest不同。如果是空序列,pop会抛出一个异常。

Clojure总结  Leiningen 第145张

向量函数向量也支持peek和pop,但它们是从向量的末尾开始处理元素的。

Clojure总结  Leiningen 第146张

Clojure总结  Leiningen 第147张

向量自身也是函数。它接受一个索引作为参数并返回对应的值,或是当索引超过边界时,抛出一个异常。

Clojure总结  Leiningen 第148张

assoc会在指定的索引位置,关联一个新的值。

Clojure总结  Leiningen 第149张

subvec会返回向量的一个子向量。

Clojure总结  Leiningen 第150张

若未指定end,则默认为向量的末尾。

Clojure总结  Leiningen 第151张

映射表函数keys将所有的键作为序列返回,vals则将所有的值作为序列返回。

Clojure总结  Leiningen 第152张

Clojure总结  Leiningen 第153张

get会返回键对应的值,或者是返回nil。

Clojure总结  Leiningen 第154张

Clojure总结  Leiningen 第155张

映射表同时也是一个函数,以它自己的键作为参数。

Clojure总结  Leiningen 第156张

关键字同样也是函数。他接受一个容器作为参数,并在这个容器中查找其自身。

Clojure总结  Leiningen 第157张

如果在映射表中查找一个键并返回了 nil,无法确认究竟是键对应的值为 nil,还是这个键在映射表中根本就不存在。contains?函数就可以解决这个问题,它只是单纯的检测某个键是否存住。

Clojure总结  Leiningen 第158张

映射表,nil是里面的一个合法值

Clojure总结  Leiningen 第159张

Clojure总结  Leiningen 第160张

● assoc返回新增了一个键值对的映射表。

● dissoc返回移除了某些键的映射表。

● select-keys返回一个映射表,仅保留了参数传入的那些键。

● merge可以合并映射表。如果多个映射表包含了同一个键,那么最右边的获胜。

Clojure总结  Leiningen 第161张

merge-with

Clojure总结  Leiningen 第162张

merge-with与merge很类似,除了当两个或以上的映射表中有相同的键时,你能指定一个你自己的函数,来决定如何合并这个键对应的值。

Clojure总结  Leiningen 第163张

集合函数 除了clojure命名空间中可用于集合的函数外,Clojure还提供了一组位于clojure.set命名空间的函数。

● union返回的集合,包含了所有输入集合中的元素。

● intersection返回的集合,其所有元素都曾同时出现于多个输入集合中。

● difference 返回的集合,其所有元素都出现于第一个输入集合,但却未出现于第二个中。

● select返回所有元素都能与给定谓词相匹配的一个集合。

Clojure总结  Leiningen 第164张

Clojure总结  Leiningen 第165张

Clojure总结  Leiningen 第166张

Clojure总结  Leiningen 第167张

并集和差集同为集合论的一部分,除此以外它们也是关系代数(relationalalgebra)的组成部分,而后者则是诸如SQL这样的查询语言的根基。

关系代数包括六个基本的运算符:并集和差集,加上重命名(rename)、选择(selection)、投影(projection)和叉积(crossproduct)。

Clojure总结  Leiningen 第168张

关系代数与关系型数据库

rename函数可以用来给键(数据库的列)重新命名,基于一个映射表,把原来的名称改成新的。

Clojure总结  Leiningen 第169张

Clojure总结  Leiningen 第170张

project函数返回的那些映射表中,仅包含与参数匹配的键。

Clojure总结  Leiningen 第171张

Clojure总结  Leiningen 第172张

Clojure总结  Leiningen 第173张

Clojure总结  Leiningen 第174张

如果两个关系中的键名不匹配,可以传入一个keymap,将relation-1中的键名映射到relation-2中对应的键。如可以将使用:country的composers,与使用:nation的nations相连接。

Clojure总结  Leiningen 第175张

letfn宏

Clojure总结  Leiningen 第176张

Clojure总结  Leiningen 第177张

letfn与let很像,只不过它是专门用来指定局部函数的。每个声明于letfn中的函数,都可以调用自身或是其他属于同一个letfn块的函数。

lazy-seq宏

Clojure总结  Leiningen 第178张

仅当需要时,lazy-seq 才会去调用它的 body,也就是说,当 seq 被直接或是间接的调用时,lazy-seq会为后续的调用缓存结果。

Clojure总结  Leiningen 第179张

lazy-cat这个定义使用了lazy-cat,它和concat非常相像,除了它的参数仅当需要时才会被求值。

Clojure总结  Leiningen 第180张

partition

Clojure总结  Leiningen 第181张

partition能把容器拆分为一个一个大小都是size的块。

Clojure总结  Leiningen 第182张

可选的step参数指明了向下一个块移动之前,partition应该在容器中向后移动多远。如果没有指定,则step就与size相同。

Clojure总结  Leiningen 第183张

def的形态defn、defmacro和defmulti。它们最终实际上都不过是对def这个特殊形式的包装罢了。

defonce能够保证一个变量一定存在,且会为其设置根绑定值,前提是它还没有被设置过。

Clojure总结  Leiningen 第184张

defn-与defn的作用类似,只不过,它产生的是一个私有函数,只能在定义它的命名空间中可见。

Clojure总结  Leiningen 第185张

compcomp用于组合两个或更多的函数。

Clojure总结  Leiningen 第186张

首先它用自己的参数调用最右端的函数,然后将获得的结果作为参数传给次右端的函数,以此类推。

Clojure总结  Leiningen 第187张

partialpartial创建了一个新的函数

Clojure总结  Leiningen 第188张

partial会对一个函数进行部分应用(partial application)。当执行partial时,可以指定一个函数f和该函数的部分参数。随后当调用这个由partial创建的函数时,可再行指定剩余的那些参数。

Clojure总结  Leiningen 第189张

Clojure总结  Leiningen 第190张

faux-curry部分求值

Clojure总结  Leiningen 第191张

declare宏允许在一行代码里同时创建两个变量(没有初始绑定)。

Clojure总结  Leiningen 第192张

评论列表暂无评论
发表评论
微信