在 Lisp 中使用 reader macro 支持 JSON 语法

2023-05-23
阅读 3 分钟
826
Reader macro 是 Common Lisp 提供的众多有趣特性之一,它让语言的使用者能够自定义词法分析的逻辑,使其在读取源代码时,如果遇到了特定的一两个字符,可以调用相应的函数来个性化处理。此处所说的“特定的一两个字符”,被称为 macro character,而“相应的函数”则被称为 reader macro function。举个例子,单引号'就是一...
封面图

使用 call/cc 实现计数循环

2023-05-07
阅读 3 分钟
877
计数循环就是从一个数字$i$开始一直遍历到另一个数字$j$为止的循环过程。例如,下面的 Python 代码就会遍历从 0 到 9 这 10 个整数并逐个打印它们
封面图

如何在CommonLisp中解析命令行参数

2022-08-21
阅读 7 分钟
1.2k
clingon 是一个 Common Lisp 的命令行选项的解析器,它可以轻松地解析具有复杂格式的命令行选项。例如,下面的代码可以打印给定次数的打招呼信息
封面图

自己动手打印整数

2022-05-02
阅读 6 分钟
1.3k
在 Common Lisp 中,打印整数一般用函数format。例如,上面的代码会往标准输出中打印出233这个数字: {代码...} 除此之外,format还可以控制打印内容的宽度、填充字符、是否打印正负号等方面。例如,要控制打印的内容至少占据6列的话,可以用如下代码 {代码...} 如果不使用字符串形式的 DSL,而是以关键字参数的方式来实...
封面图

关于为什么Java是单派发以及Common Lisp又伟大了一次的这档子事

2021-10-16
阅读 4 分钟
2.2k
基于子类型的多态要求在程序的运行期根据参数的类型,选择不同的具体方法——例如在上述例子中,当方法letsHear中调用了参数a的方法talk时,是依照变量a在运行期的类型(第一次为Cat,第二次为Dog)来选择对应的talk方法的实例的,而不是依照编译期的类型Animal。
封面图

模拟Python中小于运算符的短路特性

2021-06-26
阅读 3 分钟
1.3k
Also unlike C, expressions like a < b < c have the interpretation that is conventional in mathematics
封面图

从AOP到method-combination

2021-06-14
阅读 5 分钟
2k
“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。

format,不只是格式化

2021-01-30
阅读 6 分钟
2.7k
《实战Common Lisp》系列主要讲述在使用Common Lisp时能派上用场的小函数,希望能为Common Lisp的复兴做一些微小的贡献。MAKE COMMON LISP GREAT AGAIN。

重构vertical-let,支持解构

2020-02-12
阅读 3 分钟
1.1k
《实战Common Lisp》系列主要讲述在使用Common Lisp时能派上用场的小函数,希望能为Common Lisp的复兴做一些微小的贡献。MAKE COMMON LISP GREAT AGAIN。

all-first-registers-to-strings

2020-01-25
阅读 2 分钟
1.3k
本文是《实战Common Lisp》系列的第一篇文章。本系列主要讲述在使用Common Lisp时能派上用场的小函数,希望能为Common Lisp的复兴做一些微小的贡献。

将二叉树写到磁盘上

2019-10-29
阅读 6 分钟
4.2k
有一阵子很好奇一个问题:MySQL到底是如何将内存中的B+树写入到磁盘文件中的。明明是一棵树,要怎样才能存储成线性的字节流呢?干脆自己动手,试着实现一个简单的版本,来帮助自己摸点门道。虽然想法很不错,不过一上来就面对噩梦级别的B+树也太为难人了,因此就先从简单的二叉树入手吧。

如何编译defun

2019-10-11
阅读 7 分钟
1.8k
在defun的语法中,第一行的字符串是这个函数的文档,可以用documentation函数获取;第二行是declaration。(不管是documentation还是declaration,也许要等到自举的那一天才能够支持了)目前只打算支持如下这般朴素的defun用法:

编译return语句

2019-09-18
阅读 5 分钟
1.7k
Common Lisp中有一个叫做return的宏,它的作用和平常在C、Java,或者Node.js里面见到的return关键字完全不一样。Common Lisp中的return用于从一个块(block)中返的,而不是从一个函数中返回。用return可以写出下面这样的代码,符号YOU-WILL-NOT-SEE-ME永远不会被打印

输出HELLO WORLD——如何编译通用的函数调用表达式

2019-08-15
阅读 5 分钟
1.7k
首先要处理一下inside-out/aux和inside-out这两个函数。之前的inside-out/aux其实一直不支持对progn的处理,需要先补充;而inside-out则可以优化一下,避免在只有一个表达式的情况下,也用progn将其包裹起来。修改后的inside-out/aux和inside-out分别如下

调用C标准库的exit函数

2019-07-10
阅读 5 分钟
1.7k
在上一篇文章中,实现了对大于号(>)的处理,那么对if表达式的编译也就是信手拈来的事了,不解释太多。在本篇中,将会讲述一下如何产生可以调用来自于C语言标准库的exit(3)函数的汇编代码。

编译大于运算符

2019-07-03
阅读 3 分钟
1.5k
原定的计划中这一篇应当是要讲如何编译if表达式的,但是我发现没什么东西可以作为if的test-form的部分的表达式,所以觉得,要不还是先实现一下比较两个数字这样子的功能吧。说干就干,我决定用大于运算符来作为例子——大于运算符就是指>啦。所以,我的目标是要编译下面这样的代码

inside-out/aux如何支持对_exit的调用

2019-06-26
阅读 4 分钟
1.4k
在上一篇文章中,新增了两个函数:inside-out以及inside-out/aux——曾经想过将inside-out/aux放到前者的函数中用labels来定义,但担心不好调试,所以剥离了出来成为一个独立的函数——inside-out基本上只是驱动了后者,真正地将嵌套表达式拆解开来的还是inside-out/aux。因此,为了让让这个编译器最终可以处理如下形式的代码

拆解嵌套的表达式

2019-06-14
阅读 3 分钟
1.6k
在上一篇文章中,jjcc2函数已经可以处理加减乘除运算表达式中的变量了。也就是说,现在它可以处理如下的代码了 {代码...} 在我的电脑上,在SLIME中依次运行下面的代码 {代码...} 会得到下列的汇编代码 {代码...} 现在所需要的,就是要实现一个功能(一般是一个函数),可以将 {代码...} 自动转换为上面所给出的progn的形...

支持四则运算中的变量

2019-06-11
阅读 3 分钟
1.5k
PS:上面的结果中的#:G564只是打印出来的时候长这个样子而已,实际地输入这段代码的话,两个#:G564其实是不同的符号,会导致未绑定的变量的错误的。

如何编译setq?

2019-06-01
阅读 4 分钟
1.9k
Common Lisp中的setq类似于其它语言中的赋值语句,它可以给一个符号对象设定一个值,类似于将一个值赋值给一个变量一样。简单起见,在jjcc2中,我会将所有的符号都作为全局的一个label来实现。也就是说,如果代码中出现了

【jjcc系列第三篇】如何编译progn

2019-05-27
阅读 2 分钟
1.6k
那要编译这种代码的话怎么办呢?一个比较直观的做法,是引入临时变量,来保存嵌套在其中的表达式的求值结果,然后再用变量来代替原本嵌套的表达式。修改后的代码可能长这个样子

支持减、乘,以及除

2019-05-23
阅读 2 分钟
1.5k
在上一篇文章中,初步搭建了一个输入Common Lisp代码,输出汇编代码的编译器的骨架,实现了二元整数的加法运算。在这个基础上,要想实现减法、乘法,以及除法就是手到擒来的事情了。只需依葫芦画瓢,补充更多的分支情况即可。

开发一个trivial的lisp编译器(一)

2019-05-17
阅读 2 分钟
2.9k
我已经记不清写过多少个lisp-like语言的解释器,以及编译成自制字节码的编译器了,但我想这一次依然不会是最后一个。我还记得之所以入坑写第一个解释器,是因为当时正好学了一点Common Lisp,数据结构的课本中又正好提到一种叫做广义表的数据结构,顿时觉得:“这个广义表不是正好可以表达CL中的atom和cons吗?”于是便尝...

更过程式的let——vertical-let

2019-03-13
阅读 2 分钟
1.6k
作为一名自诩的non-trivial的Common Lisp程序员,在编码的时候经常会遇到令人不愉快的地方,其中一个便是LET。 一段典型的LET的示例代码如下 {代码...} 大多数时候,LET不会只有一个绑定。并且,也不会只是绑定一个常量这么简单,而应当是下面这样的 {代码...} 有时候我会想看看某一个绑定的值——最好是在它计算完毕后立...

Project-Euler第69题

2019-01-28
阅读 3 分钟
1.3k
大学的时候挺喜欢解Project Euler上的题目的,尤其是它不在乎答题者使用哪一门编程语言,甚至还有很多参与者是使用pen&paper来解题的。去年开始重新开始做Project Euler上的题目,而第69题则是最近刚刚解决的一题。惭愧的是,因为不晓得欧拉函数的计算公式(甚至都没有想过欧拉函数有没有可以用来计算的公式),所以...

编写嵌套反引号的宏

2018-11-18
阅读 4 分钟
1.4k
当然了,这属于没事找事,因为完全可以把最后两个表达式放到一个prog1(这也是没事找事),或者直接点,把最后一个表达式删掉来做到同样的效果——但如果是这样的话这篇东西就写不下去了,所以我偏要用return-from。

flexi-streams用法简介

2018-09-18
阅读 5 分钟
1.9k
每过一段时间总会燃起一种用Common Lisp(下文简称CL)来写Web应用的冲动,继而就会开始感慨在CL的生态圈中居然没有一款好用的Web框架。尽管放狗搜索“common lisp web framework”可以找到一些——例如Caveman2,以及在Cliki中记录的一些其它框架。然后使用过其中一部分的人就会知道,大部分用起来的体验都不咋地。

在Common Lisp中使用宏优化尾递归函数

2018-02-26
阅读 2 分钟
1.7k
尾递归函数 通俗地讲,递归函数就是指这个函数的定义当中调用了对自己。如果一个递归函数在调用了自己后就返回,这样便是尾递归。 例如,一个计算列表的长度的递归函数的定义可能是这样的 {代码...} 而一个使用欧几里得算法计算最大公约数的递归函数,可能是这样的 {代码...} 在my-gcd中调用了自己后就返回了,那么它便...