Clojure 是JVM上的一个LISP语言变种,它比Common Lisp更强调纯函数式编程,但提供了一些STM工具以处理它所引入的状态问题。...[1 2 3]) ; => true ; 只有列表是序列.(序列是有顺序的) (seq? '(1 2 3)) ; => true (seq?...(一个无穷序列) (take 4 (range)) ; (0 1 2 3) ; 使用cons 来追加一个元素到列表或者向量的头部 (cons 4 [1 2 3]) ; => (4 1 2 3) (cons...3 2 1] ; 函数 ;;;;;;;;;;;;;;;;;;;;; ; 使用fn来创建一个函数。...用来创建一个对象 (Date.) ; ; 使用. 来调用方法. 或者使用“.方法名"简写的方式 (.
为了更加具体描述 Clojure 运行原理,会分两篇文章来介绍。 本文为第一篇,涉及到的主要内容有:编译器工作流程、Lisp 的宏机制。...一般来说,编译器包括两个部分: 前端:词法分析 → 语法分析 → 语义分析 后端:分析、优化 → 目标代码生成 Clojure 的编译器也遵循这个模式,大致可以分为以下两个模块: 读取 Clojure...(目前有数字、字符、Symbol 这三类)与一个称为read table的扩展机制(getMacro)驱动的,read table 里面每项记录提供了由特性符号(称为macro characters)到特定读取行为...根据 JVM bytecode 的规范,每个.class文件都必须由类组成,而 Clojure 作为一个函数式语言,主体是函数,通过 namespace 来封装、隔离函数,你可能会想当然的认为每个 namespace...ret = (IPersistentVector) ret.cons(((Expr) args.nth(i)).eval()); return ret.seq(); } 总结
大家好,又见面了,我是你们的朋友全栈君 摘自维基百科,原链接为:http://zh.wikipedia.org/zh/LISP 因为Clojure是Lisp的一种的方言,所以我们可以先来了解一下Lisp...这个比较小众的编程到底是什么~ ————————————————————————— LISP(全名LISt Processor,即列表处理语言),由约翰·麦卡锡在1960年左右创造的一种基于λ演算的函数式编程语言...> (atom ‘a)t> (atom ‘(a b c))()> (atom ‘())t 现在我们有了第一个需要求出自变量值的操作符,让我们来看看 quote 操作符的作用——通过引用(quote)一个表...反之一个被引用的表仅仅被视为表 > (atom ‘(atom ‘a))() 引用看上去有些奇怪,因为你很难在其它语言中找到类似的概念,但正是这一特征构成了 Lisp 最为与众不同的特点——代码和数据使用相同的结构来表示...,而我们用 quote 来区分它们。
可以使用quote操作符定义一个符号,也可以单引号'开头来简单表示一个符号,如下面的示例: > (quote a) a >'a a 在Lisp/Scheme 中,通常都需要对表达式进行求值,而符号(通常...la 3) ; 取得列表第3项的值(从0开始) 4 > (list-set!...la 2 99) ; 设定列表第2项的值为99 99 > la (1 2 99 4) > (define y (make-list 5 6)) ;创建列表 > y (6 6 6 6 6) 在上面的例子中...我们可以按照这个英语单词在日常生活中最常见的意思,比如一个坐标点,来想象这个最基础的数据结构。比如坐标(1,2)是一个点对。一个点对包含两个指针,每个指针指向一个值。我们用函数cons构造点对。...定义局部变量需要使用let表达式,如下所示: > (let ((x 1) (y 2)) (+ x y)) 3 这里定义了两个变量:x和y,定义的时候给它们分别绑定一个初始值1和2。
语言,但是随着工业界越来越多的应用函数编程语言,如Clojure、Scala、Racket,以及软件开发使用并发的趋势(见文章[2]),重读SCIP是很有意义的。...Lisp基本语法 Lisp的原始定义在John McCarthy1960发表的论文[3]。 Lisp[4]是一个语言族,包括Common Lisp和Scheme,二者区别见[5]。...构造数据抽象 闭包 (这里指的不是匿名函数) 是在处理符合数据中的一个关键思想:用于组合数据对象的粘合剂,不但能用于组合基本的数据对象,同样也可以用复合数据的对象。...Wiki: 闭包是引用了自由变量的函数 序对 用来粘合两个对象,用法: (define x (cons 1 2)) (car x) ; 1 (cdr x) ; 2 序对的一种定义: (define...(car__ (cons__ 33 99)) ;33 (cdr__ (cons__ 33 99)) ;99 序列(列表) 可看做嵌套的序对: (list ...
虽然从实际上真实电路的角度来说,与非门、或非路一般比起与、或门更为简单,但一般情况下我们可能更喜欢从与、或、非说起。 与、或、非这三个门级的逻辑符号如下: ? ...这两个箭头代表的是,序偶里前后两个存的是值的引用,而不是值。这一点非常重要,利用这个性质可以构造很多的数据结构,比如最简单的列表(或者也可以叫链表)。 ...实际上就是先造出列表来表示门和各个输入信号,然后再操作pair的第二个元素指向这个列表。 对于非门只会有一个输入信号, (define (not-gate x y) (set-cdr!...x (cons 'or input-list))) 注意这里,input-list是输入信号列表,本来就是列表,所以只需要用cons把'and或者'or接在前面即可造出需要的完整列表了。 ...Lisp作为弹性十足的语言,有多种方式来支持面向对象。
Clojure与Lisp "Lisp 不是一门语言,它是一种构建素材。"...觉得必须实现共同需要的一个方法,使计算机能够处理链表中的符号数据,允许语言的处理、信息存入和检索、定理证明的过程机器化。IBM是首先对人工智能开发有兴趣的商业机构之一。...在其他语言中,这种形式只是经过解析在后台产生,但是Lisp直接采用它作为表达形式。它由列表构成,而列表则是Lisp的基本数据结构。 用一门语言自己的数据结构来表达该语言,这被证明是非常强大的功能。...如果你创造了一种新语言,其中有car、cdr、cons、quote、cond、atom、eq这样的功能,还有一种把函数写成列表的表示方法,那么在它们的基础上,你完全可以推导出Lisp语言的所有其他部分。...Clojure 还是一个动态类型的语言 我们可以选择添加类型信息来提高代码中的关键路径的性能。
根据阮一峰大佬的说法,Lisp并非是一种编程语言,而是一种理论演算的思想。是从纯数学理论发展出的语言,而非为了某种编程开发的需要而设计的。因此虽然是诞生自上世纪五十年代,但至今仍未过时。...比如4 + 5的运算,在Lisp中写成: (+ 4 5) 在Lisp中,所有的运算的外围都需要一个括号,先写运算符,再写运算需要的参数。...打包pair也有一个专门的操作符,叫做cons。不要问我为啥是这个奇怪的名字,我也不知道…… (cons 1 2) 比如上面的代码,我们创建了一个(1 2)的pair。...除了cons之外还有三个常用的符号,分别是car,cdr和nil。car用来返回pair中的第一个元素,cdr用来返回pair中的第二个元素,nil表示一个空的list。...使用cons一个一个嵌套非常麻烦,所以Lisp中专门提供了一个操作符叫做list,用来直接创建list。 符号 问题来了,我们怎么在Lisp当中区分变量和符号呢?
与此同时,John McCarthy 发明了Lisp语言,现代的Clojure就是Lisp的方言之一。1966年,Niklaus Wirth发明了Pascal。...是第一个使用Hindley-Milner type inference algorithm的语言 Lisp和ML都是call-by-value,但是Haskell则是call-by-name Lisp...统计在座的一共有多少人数。我们都知道从某个人开始依次报数,最后得到的数字就是总人数,其实这就是一种不可变计算的游戏,为什么这么说呢?因为报数其实一个计算的过程,第一个人计算出1这个数,传递给第二个人。...在多并发的情况下,就得用读写锁来控制。所以不可变性特别利于并发。 ? 不可变性 不可变的链式结构 好了,现在我们有个新的需求,设计一个不可变列表收集大家的名字。...每个节点存储一个姓名的字符串,并且有个指针指向下一个节点。但是这也打破了列表的不可变性。怎么办?我们可以把新的节点指向旧有的列表,然后返回一个新的列表。这就是不可变列表实现的机制。
由于Racket等Lisp方言通常使用S表达式作为语法,其与市面上常见的编程语言语法有较大差异,因此在这里简要介绍一下本文所使用到的部分。...例如(* 1 2),其中*表示该表达式是一个乘法运算,而1和2,则作为该乘法运算的两个参数。在描述数据时,如果与描述程序的S表达式同时存在时,便需要对其进行区分标记。...2.3.2 define与lambda 当需要定义一个符号时,可以使用define来实现,例如定义x等于5,则可以表达成(define x 5),后续使用x时则等价于使用5。...3.1.1 解析器的接口定义 在实现单元构建之前,需要先来梳理一下解析器的功能。...foldr和其他语言中的reduce函数相同,不过是从列表的末尾开始递归。
Lisp 你可能听过,这里我们不深入研究它,但后面的 Pair 是啥,它其实是一种很简单、很常见的数据结构,用 TyepScript 表示就是这样: // 创建一个 pair function cons...pair 的函数名就是 cons,还有它的两个操作 car 和 cdr 也是这个名字,因此本文也都用这个名字。...但我们这里讨论的是利用了数组去实现的,有没有别的方法去实现这种数据结构呢?答案当然是有的啦,下文将会给出仅利用函数的方式来实现这种数据结构,以及仅用函数去实现链表、二叉树。...Pair 的函数式实现 因为本人一开始是想在自己写的的一个函数式方言的解释器里加上 pair 这个类型的,因此看了 Pair 的函数式实现,如下: ;; 代码从 Wiki 摘录 ;; https://...挑战:函数式二叉树 上面的讨论已经实现了链表,而链表里一个最特殊的地方便是引用,如果引用变成两个,链表就可以推广成二叉树。
但问题是,我们在递归的时候拿不到当前下标这个变量。所以进而可以想到,只有一个参数递归肯定是解决不了的,我们至少需要两个参数。 在不改动原有函数签名的情况下,唯一的办法就是使用高阶函数。...你需要用到一个辅助函数:cons-all。...要实现cons-all函数,需要用到内置的map过程。cons-all接收一个元素和一个list,将这个元素插入到list中的每个元素作为开头。...Python代码转换成Lisp来实现,其实只要Python写得出来,Lisp也一样可以,语法虽然不同,但是核心原理是一样的。...这两个表达式可以用下图来表示: 使用这个规则来实现let-to-lambda过程,它会将let特殊类型转化成lambda表达式。
使用cons过程创建pair,它接收两个参数: pair中的元素展示的时候中间会以点分隔。...我们可以使用car和cdr过程来分别获取pair中的第一和第二个元素: 我们也可以嵌套cons来让一个pair中的元素是另外一个pair 你可能会好奇,为什么第一个例子中((1 . 2) . 3)的第一个点在第二个例子中消失了...再来看看这个pair的结构: 这里我们创建了一个well-formed list,因为我们cons过程的第二个参数是另外一个cons表达式或者是nil。...注意到操作数会在过程执行之前被evaluate Quote Form 我们也可以使用引号形式来创建list,它也会根据我们的输入创建一个一模一样的list。...我们可以使用define来创建一个过程,语法如下: 这个表达式根据我们给定的参数以及运行的逻辑(body)创建了一个函数,并将它赋值给了name。
本文是个人对第二章:欢迎来到 Lisp——ANSI Common Lisp 中文版 一文中习题的解答。 1....使用 car 与 cdr 来定义一个函数,返回一个列表的第四个元素。 答案: (defun get-forth(lst) (car (cdr (cdr (cdr lst))))) 4....只使用本章所介绍的操作符,定义一个函数,它接受一个列表作为实参,如果有一个元素是列表时,就返回真。...接受一个列表,并返回 a 在列表里所出现的次数。...一位朋友想写一个函数,返回列表里所有非 nil 元素的和。他写了此函数的两个版本,但两个都不能工作。请解释每一个的错误在哪里,并给出正确的版本。
/lib/list/294 segmentfault:https://segmentfault.com/t/lisp common-lisp:https://common-lisp.net/ 一个国外教程网...2)《ANSI Common LISP》Paul大神的作品,他的《黑客与画家》是必读的经典,会改变三观的说。...4)《Practical Common Lisp》大神田春翻译的中文版《实用Common Lisp编程》已经出版。 5)《On Lisp》也是Paul大神的作品,好像是进阶修炼版本。...8)《Artificial Intelligence :A Modern Approach》《人工智能:一种现代方法》看了个开头,从人工智能在各个学科中的基础开始,一开始就来列人名了,哲学,数学,心理学...,计算工程,认知科学,从古希腊到近现代,有一个算一个大神全到了。
挫败感的主要来源是对 ELisp 里相关概念的不熟悉,比如 xref 为了能打开 symbol 定义的文件,需要提供一个 xref-location 对象,默认提供了两种实现,xref-buffer-location...file 这个比较直观,传入 file/line/column 即可,但是我 buffer 这个则需要传入一个 position,但没说 position 怎么构造,我就猜 position 是个 (line.... column) 的 cons?...要知道 Lisp 的一重要提高生产效率的工具是 REPL,没有 demo 让我复制,我怎么在 REPL 里测试?...: 最后,再推荐一个教程,供有其他 Lisp 经验的程序员快速使用 ELisp。
借我司的一位牛人的原话:看一个人会不会测试驱动开发,不是看他的测试写得好不好,而是要看他是不是始终从测试出发去解决问题。脑子里条件反射的就是测试该怎么测?这种才是测试驱动开发的实质。...我们知道,在动态类型语言中,arity指的是方法参数的个数,这里的1和2其实表明的就是join有两个重载的方法,分别接受一个参数和两个参数。更进一步,arity是方法(函数)实现静态多态的依据之一。...这些都比较好理解,不过这里其实出现了两个新的玩意(当然也不是一蹴而就的,认识之后才重构成这样)。一个是\\ ".",还有一个是|>。...第一个比较容易猜,叫做默认参数(default arguments);第二个有Clojure基础的也手到擒来,叫做管道操作符(pipe operator),用来将左边表达式的结果传入右边方法的首个参数。...和Clojure(绝大数Lisp)中的(cons dir_name children)类似。 操作符|除了可以前置列表元素,递归解构也是一把好手。 defp decorate(is_last?
使用clojure.java.io/writer 我们在项目的根目录新建numbers.txt,内容是多行的数字对,如下: 1.3 2.7 10000 1 -1 1 我们需要把每行两个数字,和它们相加的结果写入到...-0.934 0.609" "ATOM 6 H 0.716 1.404 0.137"))) 然后使用(map (fn [[name atoms]] ...)将每组里面的两个列表合成为一个列表...惰性序列是用(lazy-seq [& body] )宏创建出来的。lazy-seq仅在需要的时候才会去调用它的body。 当repl尝试pretty-print惰性序列的结果时,才会进行变现操作。...有了上面的知识点,我们来考察with-open和(take 2 (line-seq ))的关系。...带着这个疑惑,看看line-seq的源代码 (when-let [line (.readLine rdr)] (cons line (lazy-seq (line-seq rdr))))) 是不是有种豁然开朗的感觉
从很小我们 就知道,自然数有无限多个。 小朋友都对巨大的数有一种天然的憧憬,以至于很多人都会想过这么一个问题,我们可以表示出多大的数? ...运算符号的演化 我们最先学会的运算符号是加法,很快我就学会了相同的数连加。 ...8个2相乘,写起来如下 2×2×2×2×2×2×2×2 于是有了乘方来简化,上述表示为28 有了乘方,终于有了第一个大杀器。...葛立恒数 这是曾经出现在数学证明中最大的自然数,不过后面被另外一个数学证明中的TREE(3)刷新纪录。这两个数都与图的染色有关,此处不深入。 ...Scheme来表示高德纳箭头 因为高德纳箭头的高阶箭头有个很简单的往低阶箭头上展开的关系,所以用Scheme很容易表示,毕竟Lisp是很容易表示递归的。
领取专属 10元无门槛券
手把手带您无忧上云