老古董Lisp实用主义入门教程(12):白日梦先生的白日梦

在这里插入图片描述

白日梦先生的白日梦

白日梦先生已经跟着大家一起学Lisp长达两个月零五天!

  1. 001 粗鲁先生Lisp再出发
  2. 002 懒惰先生的Lisp开发流程
  3. 003 颠倒先生的数学表达式
  4. 004 完美先生的完美Lisp
  5. 005 好奇先生用Lisp来探索Lisp
  6. 006 好奇先生在Lisp的花园里挖呀挖呀挖
  7. 007 挑剔先生给出终止迭代的条件
  8. 008 挠痒痒先生建网站记
  9. 009 小小先生学习Lisp表达式
  10. 010 聪明先生拒(ji)绝(xu)造轮子
  11. 011 没人先生学习Lisp函数

他已经能够:

  • 安装库文件、探索库函数、调用库函数
  • 定义函数、调用函数
  • 操纵列表
  • 递归、迭代
  • 表达式替换,表达式求值
  • 判断相等
  • 建立一个网站!!!

白日梦先生自觉天下无敌,接下来呢?他想得很简单,那就是编一个quicklisp排名第一的库给大家用!

梦想还是要有,万一实现了呢?

这就是白日梦先生秉持的信念!

头号敌人

白日梦先生考虑好自己的目标,花了大概三个小时详细体验实现之后自己在知乎论坛、CSDN、博客园、大型交友网站上获得大量反馈的情景,再详细设计自己面对网友如潮的点赞、收藏、关注和评论之后的表情、语气、回复。

然后,就没有然后了,因为白日梦先生他毕竟是白日梦先生,他只需要梦想,不需要现实。

白日梦先生的头号敌人,名叫不可能先生。

他哈哈大笑(他总是先哈哈大笑),对着白日梦先生说:做梦吧你,这不可能!

在这里插入图片描述

白日梦先生和不可能先生打开了quicklisp收录库链接

Quicklisp收录库链接

这个排名是按照#'string<函数的结果排序的,也就是按照字母顺序排序的。

白日梦先生脸微微发热,心怦怦跳,难道,这一次的梦想真的额能够实现?

在这里插入图片描述

那么很简单,只需要编一个库,取名为0xxxx,那么就可以排在目前排第一名的1am之前了!

那么这个1am是什么呢?好奇先生已经停不住了。

排名第一1am

不管三七二十一,好奇先生先在REPL中输入命令,想看看这个库到底是什么。

(ql:quickload '1am)
To load "1am":Load 1 ASDF system:1am(1AM); Loading "1am"

可以看到,这个库定义了一个ASDF系统,名字叫1am。只要能够加载,好奇先生就能够为所欲为。

(require 'explore-lisp)(multiple-value-list (el:dir '1am))
NIL((1AM:RUN 1AM:*TESTS* 1AM:SIGNALS 1AM:TEST 1AM:IS) 5)

只有区区五个符号,而且,看起来似乎是一个测试库。好奇先生猜测。

这完全难不倒好奇先生,只要运行下面的命令,这个库的深浅或者长短就完全暴漏出来了呢!

(el:export-all-external-symbols '1am :start-level 2)
NIL

*TESTS*

1AM:*TESTS*[symbol]*TESTS* names a special variable:Value: NILDocumentation:A list of tests; the default argument to `run'.

IS

1AM:IS[symbol]IS names a macro:Lambda-list: (FORM)Documentation:Assert that `form' evaluates to non-nil.Source file: /home/qchen/quicklisp/dists/quicklisp/software/1am-20141106-git/1am.lisp

RUN

1AM:RUN[symbol]RUN names a compiled function:Lambda-list: (&OPTIONAL (TESTS *TESTS*))Derived type: (FUNCTION (&OPTIONAL T) (VALUES &OPTIONAL))Documentation:Run each test in the sequence `tests'. Default is `*tests*'.Source file: /home/qchen/quicklisp/dists/quicklisp/software/1am-20141106-git/1am.lisp

SIGNALS

1AM:SIGNALS[symbol]SIGNALS names a macro:Lambda-list: (CONDITION &BODY BODY)Documentation:Assert that `body' signals a condition of type `condition'.Source file: /home/qchen/quicklisp/dists/quicklisp/software/1am-20141106-git/1am.lisp

TEST

1AM:TEST[symbol]TEST names a macro:Lambda-list: (NAME &BODY BODY)Documentation:Define a test function and add it to `*tests*'.Source file: /home/qchen/quicklisp/dists/quicklisp/software/1am-20141106-git/1am.lisp

1am的五脏六腑

而且,好奇先生还直接看到源文件的地址,那就去好好看看!

> wc -l *27 1am.asd105 1am.lisp114 README.md246 total

原来,这个排名第一的库,就只有三个文件,总共246行,代码就只有132行!

ASDF 定义文件

;;; Copyright (c) 2014 James M. Lawrence
;;; 
;;; Permission is hereby granted, free of charge, to any person
;;; obtaining a copy of this software and associated documentation
;;; files (the "Software"), to deal in the Software without
;;; restriction, including without limitation the rights to use, copy,
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
;;; of the Software, and to permit persons to whom the Software is
;;; furnished to do so, subject to the following conditions:
;;; 
;;; The above copyright notice and this permission notice shall be
;;; included in all copies or substantial portions of the Software.
;;; 
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
;;; DEALINGS IN THE SOFTWARE.(defsystem :1am:description "A minimal testing framework.":license "MIT":author "James M. Lawrence <llmjjmll@gmail.com>":components ((:file "1am")))

代码文件

;;; Copyright (c) 2014 James M. Lawrence
;;;
;;; Permission is hereby granted, free of charge, to any person
;;; obtaining a copy of this software and associated documentation
;;; files (the "Software"), to deal in the Software without
;;; restriction, including without limitation the rights to use, copy,
;;; modify, merge, publish, distribute, sublicense, and/or sell copies
;;; of the Software, and to permit persons to whom the Software is
;;; furnished to do so, subject to the following conditions:
;;;
;;; The above copyright notice and this permission notice shall be
;;; included in all copies or substantial portions of the Software.
;;;
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
;;; DEALINGS IN THE SOFTWARE.(defpackage #:1am(:use #:cl)(:export #:test #:is #:signals #:run #:*tests*))(in-package #:1am)(defvar *tests* nil "A list of tests; the default argument to `run'.")
(defvar *pass-count* nil)
(defvar *running* nil)
(defvar *failed-random-state* nil)(defun %shuffle (vector)(loop for i downfrom (- (length vector) 1) to 1do (rotatef (aref vector i) (aref vector (random (1+ i)))))vector)(defun shuffle (sequence)(%shuffle (map 'vector #'identity sequence)))(defun call-with-random-state (fn)(let ((*random-state* (or *failed-random-state*(load-time-value (make-random-state t)))))(setf *failed-random-state* (make-random-state nil))(multiple-value-prog1 (funcall fn)(setf *failed-random-state* nil))))(defun report (test-count pass-count)(format t "~&Success: ~s test~:p, ~s check~:p.~%" test-count pass-count))(defun %run (fn test-count)(let ((*pass-count* 0))(multiple-value-prog1 (call-with-random-state fn)(report test-count *pass-count*))))(defun run (&optional (tests *tests*))"Run each test in the sequence `tests'. Default is `*tests*'."(let ((*running* t))(%run (lambda () (map nil #'funcall (shuffle tests)))(length tests)))(values))(defun call-test (name fn)(format t "~&~s" name)(finish-output)(if *running*(funcall fn)(%run fn 1)))(defmacro test (name &body body)"Define a test function and add it to `*tests*'."`(progn(defun ,name ()(call-test ',name (lambda () ,@body)))(pushnew ',name *tests*)',name))(defun passed ()(write-char #\.);; Checks done outside a test run are not tallied.(when *pass-count*(incf *pass-count*))(values))(defmacro is (form)"Assert that `form' evaluates to non-nil."`(progn(assert ,form)(passed)))(defun %signals (expected fn)(flet ((handler (condition)(cond ((typep condition expected)(passed)(return-from %signals (values)))(t (error "Expected to signal ~s, but got ~s:~%~a"expected (type-of condition) condition)))))(handler-bind ((condition #'handler))(funcall fn)))(error "Expected to signal ~s, but got nothing." expected))(defmacro signals (condition &body body)"Assert that `body' signals a condition of type `condition'."`(%signals ',condition (lambda () ,@body)))

这样就非常清楚了,这个库通过ASDF定义了一个系统,然后定义了几个宏和函数,用来进行测试。

  • test 定义一个测试函数,然后将这个函数加入到*tests*列表中
  • is 用来断言一个表达式是否为真
  • signals 用来断言一个表达式是否会抛出一个特定的异常
  • run 用来运行*tests*列表中的所有测试函数
  • *tests* 用来存放所有的测试函数,作为run的默认参数

1am使用示例

完全照搬自1amREADME.md文件,挠痒痒先生对此负全责。

首先是定义测试的部分,相当透明。

(defpackage :example (:use :cl :1am))
(in-package :example)(test foo-test(is (= 1 1))(is (zerop 0)))(test bar-test(signals simple-error(error "bar!")))
#<PACKAGE "EXAMPLE">#<PACKAGE "EXAMPLE">FOO-TESTBAR-TEST

简单测试

接下来是简单的测试,有几种运行测试的办法。

  • 直接运行run函数,会运行*tests*列表中的所有测试函数
  • 运行test函数(真的是一个普通的函数),会运行指定的测试函数
  • 直接构造一个测试函数列表,作为参数传递给run函数
  • 设置*tests*列表,然后运行run函数

实际上,这样就可以满足定位bug,快速测试的所有需求了。由于Lisp的动态特性,还能够在调试中动态定义测试函数,加入运行。

(in-package :example)
(run)
#<PACKAGE "EXAMPLE">FOO-TEST..
BAR-TEST.
Success: 2 tests, 3 checks.
(foo-test)
FOO-TEST..
Success: 1 test, 2 checks.
(run '(bar-test))
BAR-TEST.
Success: 1 test, 1 check.
(setf *tests* '(foo-test)) 
(run)
(FOO-TEST)FOO-TEST..
Success: 1 test, 2 checks.

探索永不停止

这个排名第一的测试库1am,用起来非常简单,整个设计非常透明,代码量也很小,其实对于复杂系统的测试而言,这可能是一个很大的优点。

好奇先生看了一眼在做白日梦的白日梦先生和觉得什么都不可能的不可能先生,心里想,其实Common Lisp还真有些库是大家都在引用的,比如alexandria,不行再把alexandria好好探索一下?

好奇先生的时间快速飞逝,deadline也不停tik-tok-tik-tok。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/434631.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

手游和应用出海资讯:三七新游首月收入突破700万元;领英尝试推出游戏功能以增加用户使用时长

NetMarvel帮助游戏和应用广告主洞察全球市场、获取行业信息&#xff0c;以下为9月第四周资讯&#xff1a; ● 《AFK Journey》收入突破 1.5 亿美元 ● 《黑神话&#xff1a;悟空》IGN年度游戏投票第一掉至第三 ● 三七发布新游首月收入突破700万元 ● 开罗游戏《哆啦A梦的铜锣烧…

Java SPI 原理、样例

在 Java 中&#xff0c;SPI&#xff08;Service Provider Interface&#xff09;全称为服务提供者接口&#xff0c;它是一种用于实现框架扩展和插件化的机制。 一、SPI 作用 允许在运行时动态地为接口查找服务实现&#xff0c;而不需要在代码中显式地指定具体的实现类。 这使得…

关系模型与关系代数——数据库原理 总结2

2.1 关系模型 关系数据结构 关系模型的数据结构是二维表&#xff0c;亦称为关系。关系数据库是表的集合&#xff0c;即关系的集合。表是一个实体集&#xff0c;一行就是一个实体&#xff0c;它由有关联的若干属性的值所构成。 关系模型的相关概念 列就是数据项 或 字段 或 属…

基于SpringCloud的微服务架构下安全开发运维准则

为什么要进行安全设计 微服务架构进行安全设计的原因主要包括以下几点&#xff1a; 提高数据保护&#xff1a;微服务架构中&#xff0c;服务间通信频繁&#xff0c;涉及到大量敏感数据的交换。安全设计可以确保数据在传输和存储过程中的安全性&#xff0c;防止数据泄露和篡改。…

Study--Oracle-09--部署Openfiler存储服务器

免费的存储服务器软件有FreeNAS 和 Openfiler。 其中Freenas的网站上只有i386及amd64的版本,也就是说Freenas不能支持64位版本的Intel CPU,而Openfiler则提供更全面的版本支持,在其网站上可以看到支持多网卡、多CPU,以及硬件Raid的支持,还有10Gb网卡的支持。 Openfiler能把…

【RocketMQ】RocketMQ发送不同类型消息

&#x1f3af; 导读&#xff1a;本文介绍了RocketMQ消息队列系统中的几种消息发送模式及其应用场景&#xff0c;包括同步消息、异步消息以及事务消息。同步消息确保了消息的安全性&#xff0c;但牺牲了一定的性能&#xff1b;异步消息提高了响应速度&#xff0c;适用于对响应时…

演示:基于WPF的DrawingVisual开发的频谱图和律动图

一、目的&#xff1a;基于WPF的DrawingVisual开发的频谱图和律动图 二、效果演示 波形图 极坐标 律动图极坐标图 律动图柱状图 Dock布局组合效果 三、环境 VS2022,Net7,Win10&#xff0c;NVIDIA RTX A2000 四、主要功能 支持设置起始频率&#xff0c;终止频率&#xff0c;中心…

【HTTP 和 HTTPS详解】3

HTTP 状态代码 HTTP 状态代码是服务器发送给客户端的三位数字&#xff0c;用于指示客户端请求的结果。它们分为五类&#xff1a;信息性&#xff08;100-199&#xff09;、成功&#xff08;200-299&#xff09;、重定向&#xff08;300-399&#xff09;、客户端错误&#xff08…

【移植】Combo解决方案之W800芯片移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 本方案基于 OpenHarmony LiteOS-M 内核&#xff0c;使用联盛德 W80…

[论文精读]Membership Inference Attacks Against Machine Learning Models

中文译名&#xff1a;针对机器学习模型的成员推理攻击 会议名称&#xff1a;2017 IEEE Symposium on Security and Privacy (SP) 发布链接&#xff1a;Membership Inference Attacks Against Machine Learning Models | IEEE Conference Publication | IEEE Xplore CODE:Git…

【计算机网络】Tcp报文的组成,Tcp是如何实现可靠传输的?

Tcp的报文组成 TCP&#xff08;传输控制协议&#xff09;是计算机网络中一种重要的传输协议&#xff0c;其报文组成包括多个字段&#xff0c;每个字段具有特定的含义。以下是TCP报文头的主要组成部分&#xff1a; 源端口号&#xff08;Source Port&#xff09;&#xff1a;占用…

C语言 | Leetcode C语言题解之第445题两数相加II

题目&#xff1a; 题解&#xff1a; struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){int stack1[100];int stack2[100];int top1 0;int top2 0;int carry 0;int sum 0;struct ListNode* temp NULL;struct ListNode* head NULL;while (l1) {…

有关若依菜单管理的改造

导言&#xff1a; 搞了个后端对接若依前端&#xff0c;对接菜单管理时候懵懵的就搞完了&#xff0c;也是搞了很久。记一下逻辑和要注意的东西&#xff0c;以后做想似的能有个改造思路。 逻辑&#xff1a; 主要是要把后端传过的数组列表做成类似 这样的&#xff0c;所以要转格式…

git工具指令

下面是常用的Git命令清单&#xff0c;几个专用名称的译名如下&#xff1a; Workspace &#xff1a;工作区 Index /Stage&#xff1a;暂存区 Repository&#xff1a;仓库区&#xff08;或本地仓库&#xff09; Remote&#xff1a;远程仓库新建代码库 在当前目录新建一个Git代…

如何在银河麒麟操作系统中查看内存页大小

如何在银河麒麟操作系统中查看内存页大小 1、操作步骤2、注意事项 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在操作系统中&#xff0c;内存页大小&#xff08;Page Size&#xff09;是一个重要的概念&#xff0c;它决定了操作系统如何…

GPT理论

1.GPT发展 Transformer是一个用作翻译任务的模型&#xff0c;谷歌出品。 GPT全称 lmproving Language Understanding by Generative Pre-Training&#xff0c;用预训练语言理解模型。OPENAI出品。 BERT全称Pre-training of Deep BidirectionalTransformers for Language Unde…

深度学习反向传播-过程举例

深度学习中&#xff0c;一般的参数更新方式都是梯度下降法&#xff0c;在使用梯度下降法时&#xff0c;涉及到梯度反向传播的过程&#xff0c;那么在反向传播过程中梯度到底是怎么传递的&#xff1f;结合自己最近的一点理解&#xff0c;下面举个例子简单说明&#xff01; 一、…

828华为云征文|部署个人知识管理系统 SiyuanNote

828华为云征文&#xff5c;部署个人知识管理系统 SiyuanNote 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 SiyuanNote3.1 SiyuanNote 介绍3.2 SiyuanNote 部署3.3 Siyua…

WebSocket实现在线聊天室

项目实现源码&#xff1a; 前端源码 后端源码 1.常见的消息推送方式 1.1 轮询 1.1.1 轮询的概念 客户端以固定的事件间隔&#xff08;例如每秒或几分钟&#xff09;向服务器发送HTTP请求&#xff0c;服务器收到请求后&#xff0c;处理请求并返回数据给客户端 轮询具体实现htt…

element-plus中日历组件设置起始为周一

问题描述 element-plus中的日历组件默认是周日到周六&#xff0c;因业务需求&#xff0c;需要实现从周一到周日的顺序。 解决方式 引入dayjs及本地语言包&#xff0c;使用本地时区即可。 import dayjs from dayjs import dayjs/locale/zh-cn ... // 这一句是为了让日历使用本地…