Common Lisp学习之九:使用包

Common Lisp 学习书目 书籍 1、《Common Lisp: A Gentle Introduction to Symbolic Computation》 English Version:http://www.cs.cmu.edu/~dst/LispBook/ 中文版:无 适用于无编程基础人士 2、《Common Lisp the Language, 2nd Edition》 English Vers 阅读详情
1 读取器如何处理包
每个包都有名字,(find-package name)可以通过包名来找到一个包。解释器当前使用包存储于全局变量*package*中。包的字面形式为#<Package "pkg-name">。
(package-name pkg)可以返回一个包的名称。

包可看作一个字符串和符号的映射表,读取器使用(find-symbol name)和intern通过名字来查找特定包中的某个符号。二者的区分是后者会在符号不存在时,在包中创建这个新的符号。反向的(symbol-name symb)将反查一个符号的名字字符串表示。

通常我们使用的名字大多是非限定的,即名字里不带冒号。读取器遇到这种名字时,会将名字中所有未转义的字母转换为大写形式,然后将其传递给Intern,为名字返回一个符号对象。

含有单冒号的名字指向外部符号,即这些符号被包导出为外部可见的符号。当读取器遇到这类名字中,将名字在:号外拆分,前一部分作为包名,后一部分作为符号名,读取器查找适当的包并用它来将名称转换成符号对象。如果命名的包中不存在对应名称的符号或符号并不是外部可见,则读取器会出错。

关键字符号是另外一种含有单冒号的名字,这类符号在包为KEYWORD的包中创建并自动导出。

含有双冒号的名字可指向包中的任何符号,这通常不是好作法-因为这样可以访问到本意保留为私有的符号。

可以在REPL中,输入cl:和cl::后按tab,能看到包中的符号名称。

以#:开始的名字为unintern符号,即符号不属于任何包,每当读取器遇到这样的名字时,都会重新为此名字创建一个符号。gensym返回的就是这种名字。


2 符号与包相关术语

可访问符号:在一个给定包中,可通过find-symbol找到的符号

有两种方式使得一个符号在包中可访问。
一种是符号归属于一个包,称这个包是符号的home-package,这样包的"名称-符号"表中存在此符号的项。(package-name (symbol-package 'sym-name))可以查找一个符号最初来源于哪个包。
另一种方式是当一个包通过use使用另一个包时,前者便继承了后者导出的外部符号,从而可访问继承的符号,使得这些符号进入前者的"名称-符号"表中,称为导入。这样一个符号可以同时存在于多个包中。

包系统只允许每个名字在给定的包中指向单个符号。这样如果继承自多个包中有重名符号,或者自身定义有和使用的包中重名的符号是不允许的。必须将冲突的名称之一进行屏蔽(shadow)。每个包都维护了一个屏蔽符号表。

一个已有的符号可以从包中unintern,这会导致其被清除出"名称-符号"表,如果它是一个隐蔽符号,其也会被清除出隐蔽符号列表。

3 标准包
COMMON-LISP-USER包,也叫CL-USER包,是Lisp环境的默认载入包。所有用户自定义的符号会被导入其中。
COMMON-LISP包,这个包导出了语言标准定义的所有名字,其被CL-USER包所使用。
KEYWORD包,这个包被Lisp读取器用来创建以冒号开始的名字。

4 使用包
与Java的包机制不同,CL的包无法提供诸如谁可以调用什么函数或访问什么变量的直接控制。其只是通过控制如何将文本名转换为称号对象来提供对于名字空间的基本控制。

自定义包通过defpackge来完成:
(defpackage :cn.edu.bupt.some-name
    (:use :common-lisp ...:other-package)
    (:import-from :the-package :the-oper1 ..)
    (:shadow :op :op ...)
    (:export :oper1 :oper2 ... :opern))

包的命名类似于Java世界的作法,采用URI的反转形式。
use指定需要继承的包,系统默认继承COMMON-LISP包。包的写法可以是关键字法,这时允许使用小写字符。如果为字符串,则需要使用大写形式,如”COMMON-LISP"。

如果只需要导入特定包中的某些符号,则使用import-from的形式。可以有多个子句以从不同的包中导入。有时只需要屏蔽包中的少数符号,此时可以直接使用整个包,但把不需要的符号通过:shadow进行屏蔽。

有时从多个包继承时会遇到名字冲突,但我们需要其中的一个符号,此时使用:shoadow-import-from来导入一个冲突的符号。

需要导出符号的可以使用:export来进行说明。这样在其使用者包中,可以直接访问,而无需采用限定名的方式访问。

(in-package :name) 可以切换到指定包的上下文中,直到另一个in-package调用来改变它。其是一个宏。

此外函数或宏,如(use-package),其反转操作为(unuse-package)。(export ),其反转操作为(unexport )。(import )等,均可defpackage完成,不建议使用这些东西。

5 包定义的组织
系统要求包在它们被用到之前总是存在。最佳方式是把包定义与使用它们的源代码放到分开的文件里。
一种方式是每个包定义一个文件,另一种是把一系列包定义放在一个文件中。前者对文件的加载顺序提出了要求。
编译时,必须先加载包定义,再编译从包里读取符号的文件。对于大型项目,需要使用项目组织工具如ASDF来处理加载顺序这一问题。

另一个问题是每个文件只应该含有一个in-package形式,并且其为除注释以外的第一行。含有包定义的文件,应当以(in-package :common-lisp-user)的形式开始。

最后要注意的是包名也有冲突的可能性。

6 一些难题
第一个难题由于不经意的intern导致名字冲突的问题。例如未导入包时访问一个符号,由于此符号未定义,因而读取器会创建之,并调用求值器,求值器会导致系统会进入再启动,恢复之后导入包时,再调用同名符号时会遇到名称冲突的问题。此时需要清除先前引入的符号定义。

第二个难题是使用一个包后,新定义的符号和使用包的名称冲突,此时编译时会提示重定义,需要对其进行解决。

第三个难题是切换到其他包里工作,但未切换回CL-USER包,此时quit指令失效。

最后牢记的是:包是读取器的一部分,不是求值器的部分。

7 更多关于符号
符号是Lisp中的一种原子数据类型,每个符号都是一个对象。和数一样,符号的含义依赖于如何解释它。通常符号不对自身求值,因此对于符号需要用'引用它。读取器会将其转换为大写形式。符号可以使用字符串来当作其名字,通过symbol-name可以获取符号的名字。

每个符号都有一个属性列表,称为plist。其实际上是一个键值对,可以用get来访问其中的键值。
(get symbol 'key)
可以使用setf来设置键值。属性列表。例如可以为color键设置为red。
(setf (get symbol 'color) red)

结合包的名称-符号表,符号有如下的结构:

一个令人困惑的事情是,符号与变量从两个不同的层面上存在关联。
当符号是special variable的名字时,变量的值存在于value槽,可以用symbol-value引用。
当符号是词法变量时,其只是个占位符,编译器会将其转为一个寄存器引用或内存的地址。在编译出的代码中无法追踪这个符号(除非使用调试器外加符号表才能进行追踪),只要一有值,符号就消失了。

8 更多与包相关的概念
Package 
     这个相当于 C++ 里的 namespace,它对应的是符号所处的命名空间,并不对应到文件。package 是在代码运行时才产生的,CL 报错说某个 package 找不到并不是说哪个文件找不到,而是 CL 运行环境 
里找不到这个包的定义。  
  
System 
     一堆文件加一个 CL 版的 Makefile,组合在一起称为一个 system。这里的 "Makefile" 常见的就是 .asd 文件,"make" 对应到 ASDF。这种 "make" 还有 mk:defsystem。 
  
Module 
     一个代码集合,用 (require 'module-name) or (require :module-name) or (require "module-name") 加载此 CL 实现相关的库,具体哪种形式可行取决于 CL 实现。 有的 CL 实现可以用这个方式加载 ASDF 类型的库。 
  
Library 
     提供某功能的代码库。  

学习 Lisp 语言的相关书籍 Lisp语言难以推广的原因有很多,而相对来说,比较高额的学习成本便是这众多原因的其中之一 ...... 阅读详情

相关推荐

Common Lisp学习资源:练习与解决方案大全

本文还有配套的精品资源,点击获取 简介:Common Lisp是一种历史悠久且应用广泛的编程语言,以其独特的语法、灵活性和强大的宏系统而知名。这个项目“learninglisp”提供了丰富的练习和解决方案,帮助学习者逐步掌握Lisp编程。项目内容包括S表达式的使用,符号计算的能力,以及一系列教程、练习题目、解决方案、测试脚本、代码片段和阅读材料。通过这些资源,学习者可以深入...

weixin_36369848的博客 1364

Common Lisp包系统完全指南

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34367257的博客 511

Lisp打包下载(四本关于lisp的书)

1.Common Lisp the Language 2nd Edition 2.Editor Guide 3.LispWorks for User Guide 4.Quick reference for Common Lisp

lisp语言代替python_Reddit 为什么放弃 Common Lisp 用 Python?

无所谓开端,倘若只看结局的话,可以侧面说明:Python(Pylons) 大法好。那么简单说下 Pylons 的思想好在哪里吧,其实就是在 web 领域充分利用了 Python 的语言特性(所谓的胶水语言),ORM 有 SQLAlchemy,模板有 Mako,WSGI 这边有 WebOb,配置管理这边有 paste.deploy,表单验证有 FormEncode,会话机制有 Beaker,etc....

weixin_42539414的博客 278

《实用Common Lisp编程》

Common Lisp,缩写为 CL(不要和缩写同为CL的组合逻辑混淆),是Lisp的众多方言之一,标准由ANSI X3.226-1994定义。它是为了标准化此前众多的Lisp分支而开发的,它本身并不是一个具体的实现而是各个Lisp实现所遵循的规范。它操作的数据是动态数据类型,但也可用的类型声明来提高效率和增强安全性。

字符串查找与替换程序 文件

字符串替换函数:用于将指定字符串中指定的字符串替换为新的字符串

lisp初体验-Practical Common Lisp笔记-10.自定义宏

一般来说,凡是带有自定义的东东都会显得很专业,不过在lisp中,这才算刚刚开始。至于你信不信,反正我是信了。就让我们开始吧。 说来有些不可理喻,宏之所以难以理解,是因为它在lisp中太过自然(天生的阿),运用起来毫不费力。以至于很容易被误解为一个有意思的函数。事实上,虽然宏真的很像函数,但仅仅是像而已。他们完全不在一个层面上,抽象的层次也大不相同。 一旦理解了宏和函数的区别,恭喜你,晋...

风吹鸡蛋壳 267

Python-用CommonLisp实现的NES模拟器

用Common Lisp实现的NES模拟器

LISP 学习笔记 (二)-自定义函数

第二笔——自定义函数如果你想定义自己的函数,可以通过使用“defun” 函数,defun 函数的格式是:(defun a1 (a2) (a3))。其中: a1 是你要定义的函数标识符,通常是用字符串来表示的一个函数名称; a2 是所要定义函数的参数列表(一个或多个参数),括号是必须的; a3 是用来计算所要定义函数的表达式,也就是函数体。括号不是必须的。

xiejianming的专栏 2695

names:Emacs-Lisp 的命名空间实现

姓名 Names被设计为一种实用、完整、健壮且可调试的工具,可为您编写命名空间。 它是 Emacs 的一部分,可通过,因此每个运行至少 24.1 的 Emacs 用户都可以访问它。 使用 Names 命名 emacs-lisp 函数的示例用法。 Emacs-Lisp 的命名空间实现 Names包旨在通过四个指导原则在 Emacs 中提供命名空间的实现: 实际的 实际上有用且易于掌握。 完全的 支持 emacs-lisp 中可用的任何宏、函数或特殊形式,甚至是您或第三方定义的。 强壮的 毫无意外,经过充分测试,并有明确规定的限制。 可调试 支持edebug和eval-defun defun ,以及任何其他包开发工具。 请参阅 有关为什么需的说明,请参阅以获取对以前尝试类似事物的软件包的描述和比较。 版本兼容性 目前,整个 Emacs 24 系列 (24.1–24.4) 都支

基于NXP1778的CAN自动波特率检测

一、概念 NXP1778芯片内部自带一个CAN控制器。CAN模块由两部分组成:控制器和验收滤波器。所有的寄存器和RAM都以32位字宽度来访问。 CAN自动波特率检测主要用于以一种CAN的转换的产品中。产品中CAN部分的波特率以前都是通过网页中修改然后配置下去的,依据实际情况的考虑,如果CAN部分的波特率能够根据客户设备的改变而自动改变,将会增加其灵活性。   二、原理 根据CAN控制器的

菜鸟的痕迹专栏 5271

初识common lisp

学习任何语言都需要一个编译器,common lisp 也不例外,编写common lisp的常用工具是emacs + slime +(任意一种CL实现,常用的有SBCL,cmucl)作为初学这的我们为了方便我直接使用的lispbox,lispbox实际是是emacs+slime+ccl极大的方便了我们这些初学者,大家可以到这里下载http://common-lisp.net/project/lis

暗夜精灵 1135

Linux双网卡设置IP属于同一网段的ping方法以及现象记录分析

文章目录前言ping以及MAC地址总结 前言 写在前面:经常遇到客户将板卡上的两个网络设备的IP地址设置为同一网段的情况,比如eth0:192.168.0.232,eth1:192.168.0.30. 我的解释是,不能设置为同一网段,或者使用其中一个时候下线另外一个网卡。但是我不知道这个说法到底是根据什么,查了很多资料也没找到明确的说法,但是下面这个实验能够说明一些现象的原因。 ping以及MAC地址 首先查看网卡的信息 ifconfig 因为两个网卡都在同一个网段,所以如果这个时候直接和我们的主机(I

“逛丢一只鞋”的博客 1万+

探索Common Lisp学习宝库:Awesome Common Lisp Learning

探索Common Lisp学习宝库:Awesome Common Lisp Learning 项目介绍 欢迎来到Awesome Common Lisp Learning,这是一个专注于Common Lisp学习资源的精选列表。无论你是初学者还是经验丰富的Lisp程序员,这里都有丰富的资料帮助你深化对这一强大编程语言的理解。项目不仅提供了从基础到高级的学习路径,还包括了各种环境设置、在线参考、书籍推...

gitblog_00450的博客 418

告别密码烦恼:用Windows Server NPS给公司Wi-Fi和有线网加一道MAC地址白名单(附H3C交换机配置)

本文详细介绍了如何利用Windows Server NPS(网络策略服务器)与H3C交换机实现MAC地址白名单认证,为企业Wi-Fi和有线网络提供零密码安全方案。通过配置NPS服务器、网络策略及H3C交换机联调,实现无感知认证体验,降低运维负担,同时满足审计追溯需求。适用于中小企业网络管理,提升安全性与便捷性。

weixin_42535703的博客 367

SAP 小结

关于SAP 开发的实习就要告一段落了,从刚开始接触,到现在已经6个月了,想要很简要的把自己对SAP的理解写出来,便于以后查阅(不定期更新)。 1. 什么是SAP? 广义的SAP,可以指代SAP公司以及SAP的各种产品,它的意义要在特定语境下才能确定。一般我们所说的SAP特指SAP ERP。 SAP ERP(enterprise resource planning)是一个企业信息系统。通过这个系

Remy的博客 1953

如何通过Lisp Koans快速掌握Common Lisp:终极学习指南

Common Lisp Koans是一个语言学习练习项目,它以有序的单元测试组形式,引导学习者逐步掌握Common Lisp的众多语言特性。本文将详细介绍如何利用这个项目高效学习Common Lisp,从环境搭建到进阶练习,让你快速踏上Lisp编程之旅。 ## 什么是Lisp Koans? Lisp Koans是一种基于测试驱动的学习方法,类似于Ruby Koans和Python Koans。

gitblog_00693的博客 913

ARKit面部动画实战:如何用blend shape让数字人表情更自然(附中文对照表)

本文深入探讨了如何利用ARKit的blend shape技术驱动数字人面部动画,以实现更自然生动的表情。文章提供了详细的blend shape中文对照表,并分享了实战技巧,包括构建复合表情动画序列、处理不对称性与微表情,以及性能优化策略,旨在帮助开发者高效提升数字人的表情表现力。

weixin_29292535的博客 325

CLX:开源的Common Lisp X11客户端库

CLX:开源的Common Lisp X11客户端库 项目介绍 CLX 是一个面向 Common Lisp 的 X11 客户端库。它起源于 CMUCL 分发版本,经过修改以适应 SBCL 编译和运行,同时还整合了网络上其他 CLX 版本的精选补丁。CLX 为 Common Lisp 开发者提供了一个与 X11 系统交互的接口,使得图形界面编程在 Lisp 中变得更加可行。 项目技术分析 CLX 的...

gitblog_00451的博客 930

PySide6多线程避坑大全:信号槽崩溃、内存泄漏,这些雷我都帮你踩过了

本文深入探讨了PySide6多线程开发中的常见问题与解决方案,包括信号槽崩溃、内存泄漏等典型陷阱。通过实战案例和优化策略,帮助开发者避免UI线程操作错误、有效管理资源生命周期,并提升跨线程通信的可靠性。特别针对PySide6多线程特性,提供了线程安全日志、死锁检测等实用调试技巧。

weixin_32288959的博客 396

【数据分析】基于多组学数据整合的微生物与宿主互作网络构建及可视化分析

综上所述,本教程通过详细的步骤和方法,展示了如何整合微生物群落数据、宿主基因表达数据和代谢组数据,构建微生物与宿主互作网络,并进行可视化分析。这种方法为研究微生物与宿主之间的复杂关系提供了一种有力的工具,有助于推动相关疾病的研究和治疗。然而,在实际应用中,需要注意数据处理和分析过程中的各种问题,并结合实验验证来提高研究结果的可靠性和科学性。未来,随着多组学技术的不断发展和完善,以及数据分析方法的创新,相信我们能够更深入地理解微生物与宿主之间的互作机制,为疾病的预防、诊断和治疗提供更有力的支持。

专注生信领域 370

推荐项目:Emacs for Common Lisp(Emacs4CL)

推荐项目:Emacs for Common Lisp(Emacs4CL) 在众多编程环境之中,Emacs因其可塑性和强大的扩展性,成为许多程序员的首选。特别是对于Common Lisp这一历史悠久且充满智慧的语言,有一个名为Emacs for Common Lisp (Emacs4CL) 的项目,它简化了在Emacs中设置Common Lisp开发环境的过程,使得初学者能更快地跨过入门的门槛,让...

gitblog_00125的博客 1064

innovus: 如何让两个generate clock balance skew group?

如题,在sdc约束中两个generate clock被设置到同一个clock group中,工具虽然会生成对应的两个skew group,但是阅读ccoot_spec发现工具并没有让两个skew group进行balance,这时就需要手动设置balance skew group。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 4049

Common Lisp 编程语言深度解析

CommonLisp是Lisp家族的主要方言,作为世界上第二古老的高级编程语言,以其强大的功能和灵活性著称。它采用S-表达式和"代码即数据"的哲学,支持REPL驱动的交互式开发,并拥有独特的宏系统,可实现元编程和语言扩展。CommonLisp融合了函数式、面向对象(通过CLOS)等多种编程范式,提供高性能和动态类型检查,适合人工智能、符号计算和复杂系统开发。尽管学习曲线陡峭,但其卓越的表达力和生产力使其在特定领域保持独特价值。

bulita great world 1422

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Steel Bank Common Lisp (SBCL) 开源项目教程

Steel Bank Common Lisp (SBCL) 是一个高性能的 Common Lisp 编译器和运行时环境。它是一个开源项目,旨在提供一个高质量、高性能的 Common Lisp 实现。SBCL 不仅支持标准的 Common Lisp 语言特性,还提供了许多扩展功能,如垃圾回收、多线程支持、调试工具等。 SBCL 的核心优势在于其高性能和稳定性,使其成为许多开发者和研究者的首选 Co...

gitblog_00614的博客 1428

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

NumCL实战案例:用Common Lisp实现机器学习算法的基础步骤

NumCL是一个在Common Lisp中实现的Numpy克隆库,为开发者提供了强大的数组操作和数值计算能力。本文将通过实战案例,详细介绍如何使用NumCL构建机器学习算法的基础组件,包括数据准备、矩阵运算和模型训练等关键步骤。 ## 📊 准备工作:安装与环境配置 要开始使用NumCL进行机器学习开发,首先需要克隆项目仓库并配置Common Lisp环境: ```bash git clon

gitblog_00186的博客 796

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

上一篇: Common Lisp学习之八:异常状况处理
下一篇: Common Lisp学习之十:输出格式化控制与高级循环控制
zzulp
博客等级 码龄19年 464粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值