首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Clojure 运行原理之编译器剖析

为了更加具体描述 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(); } 总结

99930
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Lisp语言简介_c++是什么语言

    大家好,又见面了,我是你们朋友全栈君 摘自维基百科,原链接为:http://zh.wikipedia.org/zh/LISP 因为ClojureLisp一种方言,所以我们可以先来了解一下Lisp...这个比较小众编程到底是什么~ ————————————————————————— LISP(全名LISt Processor,即列表处理语言),由约翰·麦卡锡在1960年左右创造一种基于λ演算函数式编程语言...> (atom ‘a)t> (atom ‘(a b c))()> (atom ‘())t 现在我们有了第一个需要求出自变量值操作符,让我们来看看 quote 操作符作用——通过引用(quote)一个表...反之一个被引用表仅仅被视为表 > (atom ‘(atom ‘a))() 引用看上去有些奇怪,因为你很难在其它语言中找到类似的概念,但正是这一特征构成了 Lisp 最为与众不同特点——代码和数据使用相同结构表示...,而我们用 quote 区分它们。

    2.3K20

    Scheme语言实例入门--怎样写一个“新型冠状病毒感染风险检测程序” 1,表达式2,原子3,表(list) 4,点对(pair)5,向量(vector)6,变量7,

    可以使用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。

    1.5K20

    SCIP学习笔记

    语言,但是随着工业界越来越多应用函数编程语言,如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 ...

    1.6K40

    Scheme实现数字电路仿真(1)——组合电路

    虽然从实际上真实电路角度来说,与非门、或非路一般比起与、或门更为简单,但一般情况下我们可能更喜欢与、或、非说起。   与、或、非这三个门级逻辑符号如下: ?   ...这两个箭头代表是,序偶里前后两个是值引用,而不是值。这一点非常重要,利用这个性质可以构造很多数据结构,比如最简单列表(或者也可以叫链表)。   ...实际上就是先造出列表表示门和各个输入信号,然后再操作pair第二个元素指向这个列表。   对于非门只会有一个输入信号,   (define (not-gate x y) (set-cdr!...x (cons 'or input-list)))   注意这里,input-list是输入信号列表,本来就是列表,所以只需要cons把'and或者'or接在前面即可造出需要完整列表了。   ...Lisp作为弹性十足语言,有多种方式支持面向对象。

    1K20

    Clojure与LispClojure与Lisp

    ClojureLisp "Lisp 不是一门语言,它是一种构建素材。"...觉得必须实现共同需要一个方法,使计算机能够处理链表中符号数据,允许语言处理、信息存入和检索、定理证明过程机器化。IBM是首先对人工智能开发有兴趣商业机构之一。...在其他语言中,这种形式只是经过解析在后台产生,但是Lisp直接采用它作为表达形式。它由列表构成,而列表则是Lisp基本数据结构。 用一门语言自己数据结构表达该语言,这被证明是非常强大功能。...如果你创造了一种新语言,其中有car、cdr、cons、quote、cond、atom、eq这样功能,还有一种把函数写成列表表示方法,那么在它们基础上,你完全可以推导出Lisp语言所有其他部分。...Clojure 还是一个动态类型语言 我们可以选择添加类型信息提高代码中关键路径性能。

    1.9K30

    日拱一卒,伯克利CS61A,居然有Lisp这样语言……

    根据阮一峰大佬说法,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当中区分变量和符号呢?

    97540

    函数式编程简介

    与此同时,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这个数,传递给第二个人。...在多并发情况下,就得用读写锁控制。所以不可变性特别利于并发。 ? 不可变性 不可变链式结构 好了,现在我们有个新需求,设计一个不可变列表收集大家名字。...每个节点存储一个姓名字符串,并且有个指针指向下一个节点。但是这也打破了列表不可变性。怎么办?我们可以把新节点指向旧有的列表,然后返回一个列表。这就是不可变列表实现机制。

    1.7K41

    基于解析器组合子语法解析器(上)

    由于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函数相同,不过是列表末尾开始递归。

    2.7K50

    JavaScript: 挑战函数式数据结构

    Lisp 你可能听过,这里我们不深入研究它,但后面的 Pair 是啥,它其实是一种很简单、很常见数据结构,用 TyepScript 表示就是这样: // 创建一个 pair function cons...pair 函数名就是 cons,还有它两个操作 car 和 cdr 也是这个名字,因此本文也都用这个名字。...但我们这里讨论是利用了数组去实现,有没有别的方法去实现这种数据结构呢?答案当然是有的啦,下文将会给出仅利用函数方式实现这种数据结构,以及仅用函数去实现链表、二叉树。...Pair 函数式实现 因为本人一开始是想在自己写一个函数式方言解释器里加上 pair 这个类型,因此看了 Pair 函数式实现,如下: ;; 代码 Wiki 摘录 ;; https://...挑战:函数式二叉树 上面的讨论已经实现了链表,而链表里一个最特殊地方便是引用,如果引用变成两个,链表就可以推广成二叉树。

    76840

    日拱一卒,伯克利CS61A大作业,scheme 解释器(四)

    但问题是,我们在递归时候拿不到当前下标这个变量。所以进而可以想到,只有一个参数递归肯定是解决不了,我们至少需要两个参数。 在不改动原有函数签名情况下,唯一办法就是使用高阶函数。...你需要用到一个辅助函数:cons-all。...要实现cons-all函数,需要用到内置map过程。cons-all接收一个元素和一个list,将这个元素插入到list中每个元素作为开头。...Python代码转换成Lisp实现,其实只要Python写得出来,Lisp也一样可以,语法虽然不同,但是核心原理是一样。...这两个表达式可以用下图表示: 使用这个规则实现let-to-lambda过程,它会将let特殊类型转化成lambda表达式。

    1K40

    日拱一卒,伯克利教你用Lisp写递归,写完后我感觉代码更溜了

    使用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。

    65540

    我是怎样学习新编程语言

    借我司一位牛人原话:看一个人会不会测试驱动开发,不是看他测试写得好不好,而是要看他是不是始终测试出发去解决问题。脑子里条件反射就是测试该怎么测?这种才是测试驱动开发实质。...我们知道,在动态类型语言中,arity指的是方法参数个数,这里1和2其实表明就是join有两个重载方法,分别接受一个参数和两个参数。更进一步,arity是方法(函数)实现静态多态依据之一。...这些都比较好理解,不过这里其实出现了两个玩意(当然也不是一蹴而就,认识之后才重构成这样)。一个是\\ ".",还有一个是|>。...第一个比较容易猜,叫做默认参数(default arguments);第二个有Clojure基础也手到擒,叫做管道操作符(pipe operator),用来将左边表达式结果传入右边方法首个参数。...和Clojure(绝大数Lisp)中(cons dir_name children)类似。 操作符|除了可以前置列表元素,递归解构也是一把好手。 defp decorate(is_last?

    93530

    Clojure文件操作和惰性序列

    使用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))))) 是不是有种豁然开朗感觉

    3.1K30

    自然数到底可以表示到多大?

    很小我们 就知道,自然数有无限多个。   小朋友都对巨大数有一种天然憧憬,以至于很多人都会想过这么一个问题,我们可以表示出多大数?   ...运算符号演化   我们最先学会运算符号是加法,很快我就学会了相同数连加。   ...8个2相乘,写起来如下   2×2×2×2×2×2×2×2   于是有了乘方简化,上述表示为28   有了乘方,终于有了第一个大杀器。...葛立恒数   这是曾经出现在数学证明中最大自然数,不过后面被另外一个数学证明中TREE(3)刷新纪录。这两个数都与图染色有关,此处不深入。   ...Scheme表示高德纳箭头   因为高德纳箭头高阶箭头有个很简单往低阶箭头上展开关系,所以用Scheme很容易表示,毕竟Lisp是很容易表示递归

    1.4K20
    领券