老古董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: NIL
  Documentation:
    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.asd
 105 1am.lisp
 114 README.md
 246 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 1
        do (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-TEST






BAR-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.mfbz.cn/a/884548.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

构建高可用和高防御力的云服务架构第二部分:SLB负载均衡(2/5)

在现代云服务中&#xff0c;负载均衡&#xff08;Load Balancing&#xff09;是一种关键技术&#xff0c;用于优化资源利用、最小化响应时间、提高系统的可伸缩性和可靠性。负载均衡器位于客户端和服务器之间&#xff0c;根据预设的策略将请求分发到多个服务器上&#xff0c;以…

如何使用ssm实现基于web的山东红色旅游信息管理系统的设计与实现

TOC ssm716基于web的山东红色旅游信息管理系统的设计与实现jsp 绪论 1.1研究背景 从古到今&#xff0c;信息的录入&#xff0c;存储&#xff0c;检索都受制于社会生产力的发展&#xff0c;不仅仅浪费大量的人力资源还需要浪费大量的社会物资&#xff0c;并且不能长时间的保…

计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践

计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践 1. 什么是生成对抗网络&#xff1f; 生成对抗网络&#xff08;Generative Adversarial Networks&#xff0c;简称GANs&#xff09;是由Ian Goodfellow等人在2014年提出的一种深度学习模型&#xff0c;主要用于数…

JavaEE: 深入探索TCP网络编程的奇妙世界(三)

文章目录 TCP核心机制TCP核心机制三: 连接管理建立连接(三次握手)断开连接(四次挥手)三次握手/四次挥手 流程简图 TCP核心机制 前一篇文章 JavaEE: 深入探索TCP网络编程的奇妙世界(二) 书接上文~ TCP核心机制三: 连接管理 建立连接(三次握手),断开连接(四次挥手). 这里的次数…

二叉树的前序遍历,中序遍历,后序遍历(非递归方法+C语言代码)

#include<stdlib.h> #include<stdio.h> #include<assert.h> #include<stdbool.h> //定义一个二叉树结点结构体 typedef int ElemTpye; typedef struct TreeNode {ElemTpye data;struct TreeNode* left;struct TreeNode* right; }TreeNode; //创建结点 …

【中间件——基于消息中间件的分布式系统的架构】

1. 基于消息中间件的分布式系统的架构 从上图中可以看出来&#xff0c;消息中间件的是 1&#xff1a;利用可靠的消息传递机制进行系统和系统直接的通讯 2&#xff1a;通过提供消息传递和消息的排队机制&#xff0c;它可以在分布式系统环境下扩展进程间的通讯。 1.1 消息中间件…

影视站群程序大对比,苹果cmsv10 vs海洋cms

在影视站群程序领域&#xff0c;苹果CMSv10和海洋CMS是两款备受站长们青睐的程序。它们分别具备各自的优势&#xff0c;适合不同需求的站群管理和优化。以下是两者的详细对比&#xff0c;并重点介绍苹果CMS的主要优势和插件功能。 苹果CMSv10简介 maccmscn 苹果CMSv10&#x…

CV之OCR:GOT-OCR2.0的简介、安装和使用方法、案例应用之详细攻略

CV之OCR&#xff1a;GOT-OCR2.0的简介、安装和使用方法、案例应用之详细攻略 目录 GOT-OCR2.0的简介 1、更新 GOT-OCR2.0的安装和使用方法 1、安装 安装环境cuda11.8torch2.0.1 安装包 安装Flash-Attention GOT权重&#xff1a;1.43G 2、演示 3、训练 4、评估 GOT-…

记录Mac编译Android源码踩过的坑

学习Android源码&#xff0c;如果电脑配置还不错&#xff0c;最好还是下载一套源码&#xff0c;经过编译后导入到Android Studio中来学习&#xff0c;这样会更加的直观&#xff0c;代码之间的跳转查看会更加方便。因此&#xff0c;笔者决定下载并编译一套源码&#xff0c;以利于…

[Redis][哨兵][下]详细讲解

目录 1.安装部署(基于Docker)1.编排Redis主从节点2.编排Redis-Sentinel节点 2.重新选举1.redis-master宕机之后2.redis-master重启之后3.总结 3.选举原理4.总结 1.安装部署(基于Docker) 1.编排Redis主从节点 编写docker-compose.yml 创建/root/redis/docker-compose.yml&…

【web安全】——信息收集

一、收集域名信息 1.1域名注册信息 工具&#xff1a;站长之家 whois查询 SEO综合查询 1.2子域名收集 原理&#xff1a;字典爆破&#xff0c;通过字典中的各种字符串与主域名拼接&#xff0c;尝试访问。 站长之家 直接查询子域名 ip138.com https://phpinfo.me/domain/ …

StoryMaker 在文本到图像的生成过程中实现一致的字符

StoryMaker 是一种个性化解决方案&#xff0c;它不仅能保持多个角色场景中面部的一致性&#xff0c;还能保持服装、发型和身体的一致性&#xff0c;从而有可能制作出由一系列图像组成的故事。 StoryMaker 生成图像的可视化。 前三行讲述的是 "上班族 "一天的生活&…

创建javaWeb项目(详细版本)2021年2月

1、新建一个java项目 2、点击工程名称&#xff0c;找到add framework support&#xff0c;并点击 建好如图 3、分别在工程目录下创建resourse文件夹和web目录下创建classes和lib文件夹 建好如图 4、file找到 project structure 5、选中resourse 将其mark as sources 6、路径改…

关于frp Web界面-----frp Server Dashboard 和 frp Client Admin UI

Web 界面 官方文档&#xff1a;https://gofrp.org/zh-cn/docs/features/common/ui/ 目前 frpc 和 frps 分别内置了相应的 Web 界面方便用户使用。 客户端 Admin UI 服务端 Dashboard 服务端 Dashboard 服务端 Dashboard 使用户可以通过浏览器查看 frp 的状态以及代理统计信…

godot4.2入门项目 dodge_the_creep学习记录

前言 在学习博客Godot4 你的第一个2d游戏中的项目时&#xff0c;遇到了点小问题&#xff0c;记录一下。 官方项目 传送门 问题 怪兽直接从屏幕中间部分冒出来&#xff0c;以及角色出现时位于屏幕外角色被设置的背景图遮挡 解决方法 1.节点的位置没有对齐&#xff0c;正确示例…

Apache APISIX学习(2):安装Grafana、prometheus

一、Grafana安装 1、介绍 Grafana 是一个监控仪表系统&#xff0c;它是由 Grafana Labs 公司开源的的一个系统监测 (System Monitoring) 工具。它可以大大帮助你简化监控的复杂度&#xff0c;你只需要提供你需要监控的数据&#xff0c;它就可以帮你生成各种可视化仪表。同时它…

Vue-Bag-Admin 采用漂亮的 Naive UI 构建的开源中后台系统,基于 Vue3 / Vite / TypeScript 等最新的前端技术栈

这是一款完成度很高、实用性很强的 admin 前端框架&#xff0c;颜值不错&#xff0c;推荐给大家。 Vue-Bag-Admin 在官网上也直接称为 Bag-Admin&#xff0c;这是一款专门为企业项目搭建中后台管理平台的前端框架&#xff0c;基于目前最新的前端技术栈 Vue3、Vite、TypeScript…

程序设计题(65—72)

第六十五题 题目 请编写函数fun&#xff0c;它的功能是&#xff1a;计算下列级数和&#xff0c;和值由函数值返回。 例如&#xff0c;当n10&#xff0c;x0.3时&#xff0c;函数值为1.349859。 #include <conio.h> #include <stdio.h> #include <math.h> #…

5.使用 VSCode 过程中的英语积累 - Go 菜单(每一次重点积累 5 个单词)

前言 学习可以不局限于传统的书籍和课堂&#xff0c;各种生活的元素也都可以做为我们的学习对象&#xff0c;本文将利用 VSCode 页面上的各种英文元素来做英语的积累&#xff0c;如此做有 3 大利 这些软件在我们工作中是时时刻刻接触的&#xff0c;借此做英语积累再合适不过&a…

react:React Hook函数

使用规则 只能在组件中或者其他自定义的Hook函数中调用 只能在组件的顶层调用&#xff0c;不能嵌套在if、for、 其他函数中 基础Hook 函数 useState useState是一个hook函数&#xff0c;它允许我们向组件中添加一个状态变量&#xff0c;从而控制影响组件的渲染结果 示例1…