Clozure CL中文版004:使用Clozure CL

  • 0

Clozure CL中文版004:使用Clozure CL

Category:帮助手册 Tags : 

使用Clozure CL

介绍

Common Lisp标准允许在实现的细节上有相当大的自由度,并且每个特定的Common Lisp系统都有一些特性。本章描述了Clozure CL的普通用户级功能,包括可能是Common Lisp标准一部分的功能,但可能在Clozure CL实现中具有标准未描述的怪癖或细节。它还描述了标准的扩展; 也就是说,Clozure CL的功能根本不属于Common Lisp标准。

内存映射文件

在1.2版及更高版本中,Clozure CL支持内存映射文件。在支持内存映射文件(包括Mac OS X,Linux和FreeBSD)的操作系统上,操作系统可以安排一系列虚拟内存地址来引用打开文件的内容。只要文件保持打开状态,程序就可以通过读取映射范围内的地址从文件中读取值。

在某些情况下,使用内存映射文件比将文件内容读入内存中的数据结构更有效。

Clozure CL提供了功能map-file-to-ivectormap-file-to-octet-vector支持内存映射。这些函数返回其内容是内存映射文件内容的向量。读取此类向量的元素将从文件中的相应位置返回数据。

没有内存映射文件,读取文件内容的常用习惯用法可能是这样的:

(let* ((stream (open pathname :direction :input :element-type ‘(unsigned-byte 8)))

(vector (make-array (file-size-to-vector-size stream)

:element-type ‘(unsigned-byte 8))))

(read-sequence vector stream))

使用内存映射文件的结果与上面的示例相同,就像上面的示例一样,它返回一个内容与文件内容相同的向量。它的不同之处在于上面的例子在内存中创建了一个新的向量,并将文件的内容复制到其中; 使用内存映射文件而不是安排向量的元素直接指向磁盘上的文件内容,而不是先将它们复制到内存中。

载体通过返回map-file-to-ivectormap-file-to-octet-vector是只读的; 任何更改这些函数返回的向量元素的尝试都会导致内存访问错误。Clozure CL目前不支持将数据写入内存映射文件。

由Clozure CL 创建的向量map-file-to-ivector 并且map-file-to-octet-vector必须遵守Clozure CL对阵列总大小的限制。这意味着array-total-size-limit即使文件系统支持更大的文件大小,也不能使用这些函数来创建长度超过的向量。价值array-total-size-limit是(expt 2 24) 32但平台; 和(expt 2 56)在64位的平台。

map-file-to-ivector pathname element-type 元素类型[功能]

map-file-to-ivector函数尝试以路径名打开文件以进行读取。如果成功,该函数将文件的内容映射到一系列虚拟地址。如果成功,则返回一个只读向量,其元素类型由element-type给出,其内容是内存映射文件的内容。

路径

要进行内存映射的文件的路径名。

元件型

要创建的向量的元素类型。指定为类型说明符 ,用于命名其中一个signed-byte 或的子类型unsigned-byte。

返回的向量是一个位移数组, 其元素类型是(UPGRADED-ARRAY-ELEMENT-TYPE element-type)。被移位数组的目标是一个类型(SIMPLE-ARRAY element-type (*))的向量,其元素是内存映射文件的内容。

由于对齐问题,映射文件的内容在向量中开始几个字节(32位平台上的4个字节,64位平台上的8个字节)。返回的移位数组map-file-to-ivector隐藏了这种开销,但在底层的简单1维数组上操作通常更有效。给定一个置换数组(如返回的值map-file-to-ivector),该函数 array-displacement返回基础数组和元素中的位移索引。

目前,Clozure CL仅支持对内存映射文件的读取操作。如果您尝试更改返回的数组的内容map-file-to-ivector,Clozure CL会发出内存错误信号。

unmap-ivector displaced-array 位移阵列[功能]

如果参数是由返回的置换数组map-file-to-ivector,并且如果它尚未被此函数取消映射,则unmap-ivector撤消内存映射,关闭映射文件,并更改已移位数组,以使其目标为空向量(长度为零)。

map-file-to-octet-vector displaced-array 位移阵列[功能]

此函数是(map-file-to-ivector pathname ‘(unsigned-byte 8))它的同义词。它是为了方便常见的内存映射文件作为字节向量。

unmap-octet-vector displaced-array 位移阵列[功能]

此功能是其同义词 unmap-ivector

静态变量

Clozure CL支持静态变量的定义,静态变量的值在线程之间是相同的,并且可能不是动态绑定的。因此,静态变量的值在所有线程中都是相同的; 更改一个线程中的值会更改所有线程的值。

尝试动态重新绑定静态变量(例如,通过使用LET或使用变量名称作为LAMBDA表单中的参数)发出错误信号。静态变量是共享的全局资源; 动态绑定对于单个线程是私有的。

因此,静态变量提供了一种跨线程共享可变状态的简单方法。它们还提供了一种简单的方法来将竞争条件和模糊错误引入代码,因为每个线程都会读取和写入给定静态变量的相同实例。因此,您必须注意如何更改静态变量的值,并使用常规的多线程编程技术(如锁或信号量)来防止竞争条件。

在Clozure CL中,访问静态变量通常比访问尚未声明为静态的特殊变量更快。

defstatic var value &key docstring        [宏]

声明变量special,将变量赋予提供的,并将docstring分配给变量的variable文档。将变量标记为static,防止任何动态重新绑定它的尝试。任何动态重新绑定var尝试都会 发出错误信号。

保存应用程序

Clozure CL提供了该函数save-application,该函数创建一个包含存档的Lisp内存映像的文件。

Clozure CL包含一个名为lisp内核的小型可执行文件 ,它实现了Lisp系统的最低级别功能,以及一个堆栈映像,它包含大多数Lisp系统的内存中表示,包括函数,数据结构,变量,等等。当您启动Clozure CL时,您将启动内核,然后内核定位并读取图像文件,并将存档的图像恢复到内存中。一旦映像完全恢复,Lisp系统就会运行。

使用时save-application,您可以创建一个包含已修改映像的文件,该映像包含您对正在运行的Lisp系统所做的任何更改。如果您稍后将图像文件作为命令行参数传递给Clozure CL内核,则会加载您的图像文件而不是默认图像文件,Clozure CL会启动您的修改。

如果这种情况看起来像是一种创建应用程序的便捷方式,那就像预期的那样。您可以通过修改正在运行的Lisp来创建应用程序,直到它完成您想要的操作,然后使用它save-application来保留您的更改并稍后加载它们以供使用。

事实上,你可以走得更远。您可以用自己的函数替换Clozure CL的顶层函数,然后,当加载图像时,Lisp系统会立即执行您的任务,而不是使其成为Lisp开发系统的默认任务。如果您保存一个已完成此操作的映像,则生成的Lisp系统是您的工具,而不是Lisp开发系统。

你可以更进一步。您可以告诉save-application将Lisp内核添加到映像文件中。这样做会使得到的图像成为一个独立的可执行二进制文件。当您运行生成的文件时,Lisp内核会立即加载附加的映像文件并运行您保存的系统。启动的Lisp系统可以有您选择的任何行为。它可以是一个Lisp开发系统,但可以使用您的自定义; 或者它可以立即执行您的设计任务,使其成为一个专门的工具,而不是一般的开发系统。

换句话说,您可以通过交互式修改Clozure CL直到它完成您想要的任何内容来开发您喜欢的任何应用程序,然后使用它save-application来保留您在可执行映像中的更改。

在Mac OS X上,应用程序构建器 用于save-application创建应用程序包的可执行部分。双击应用程序包将运行由其创建的可执行映像save-application

同样在Mac OS X上,Clozure CL支持一种名为的对象类型macptr,它是指向外部(Mac OS)堆的指针类型。常用用户macptr对象的示例是Cocoa窗口和其他动态分配的Mac OS系统对象。

因为macptr对象是指向运行Lisp进程生命周期中存在的外部堆的指针,并且因为通过将保存的图像加载到全新的Lisp进程中来使用已保存的图像,macptr所以不能依赖保存的对象指向相同的东西从保存的图像重建时。事实上,恢复的macptr对象可能指向任何东西 – 例如代码块中间的任意位置,或者完全不存在的虚拟地址。

因此,在save-application将所有macptr对象dead-macptr 写入图像文件时将其转换为对象。A dead-macptr在功能上与a相同macptr,除了对macptr对象进行操作的代码将它们与dead-macptr对象区分开来并且可以适当地处理它们 – 例如,信令错误。

转换macptr为dead-macptr对象有一个例外:macptr指向地址0 的对象未被转换,因为始终可以依赖地址0来引用相同的东西。

常量+null-ptr+ 指的macptr是指向地址0 的对象。

在所有支持的平台上,您可以使用save-application创建一个与任何其他命令行程序一样运行的命令行工具。另外,如果您选择不预先设置的内核,你可以保存图像,然后后来把它当作一个命令行参数来运行它ccl 或ccl64脚本。

save-application filename &key toplevel-function init-file 错误处理程序 application-class clear-clos-cachespurify timpurityifymode o644prepend-kernel native[功能]

保存堆图像。

文件名

Clozure CL保存应用程序时要创建的文件的路径名。

顶级功能

启动后要执行的功能完成。toplevel是一个无参数的函数,它执行lisp系统在使用此映像启动时应执行的任何操作。

如果未提供此参数,Clozure CL将使用其默认顶层。默认的toplevel运行read-eval-print循环

初始化文件

图像启动时要加载的Lisp文件的路径名。您可以将初始化表达式放在此文件中,并在启动时使用它来自定义Lisp系统的行为。

错误处理

已保存图像的错误处理模式。提供的值确定在保存的图像未处理错误时发生的情况。有效值为:quit(Lisp退出并显示错误消息); :quit-quietly(Lisp退出时没有错误消息); 或:listener(Lisp进入中断循环,使您能够通过在侦听器中进行交互来调试问题)。如果您不提供此参数,则保存的图像将使用默认错误处理程序(:listener)。

应用级

表示已保存的Lisp应用程序的CLOS类。通常您不需要提供此参数; save-application使用该类ccl:lisp-development-system。在某些情况下,您可以选择创建自定义应用程序类; 在这种情况下,将类的名称作为此参数的值传递。

明确克洛斯缓存

如果为true,则确保在保存图像之前清空CLOS缓存。通常,您不需要提供此参数,但如果由于某种原因您希望确保在映像启动时CLOS缓存是清除的,则可以传递任何true值。

净化

如果为true,则purify在保存堆映像之前调用(实际上)。这会将不太可能变成垃圾的某些对象移动到GC未扫描的特殊内存区域(因为预计GC不会找到任何要收集的内容)。

impurify

如果为true,则impurify在保存堆映像之前调用(实际上)。(如果这两个:impurify 和:purify是真实的,首先 impurify是做,然后purify。)

impurify 将某些特殊内存区域中的对象移动到常规动态堆中,GC将对其进行扫描。

模式

一个数字,指定输出文件的模式(权限位)。

前置内核

指定要添加到已保存堆映像的文件。一个值,t用于预先添加lisp开始使用的lisp内核二进制文件。否则,值:prepend-kernel 应该是要预先添加的文件的路径名指示符。

如果前置文件是可执行的,则其执行模式位将被复制到输出文件。

此参数可用于将任何类型的文件添加到已保存的堆映像中。这在某些特殊情况下很有用。

本地人

如果为true,则将图像保存为本机(ELF,Mach-O,PE)共享库。(在尚不支持此功能的平台上,将发出警告并忽略该选项。)

*save-exit-functions*[变量]

此变量包含将在保存堆映像之前调用的0参数函数列表。用户可以根据需要向此列表添加功能。

*restore-lisp-functions*[变量]

此变量包含将在还原已保存的堆映像后调用的0参数函数列表。用户可以根据需要向此列表添加功能。

*lisp-cleanup-functions*[变量]

此变量包含将在退出lisp之前调用的0参数函数列表。

请注意,save-application退出lisp,因此在保存堆映像之前将调用此列表中的所有函数。

*lisp-startup-functions*[变量]

此变量包含将在启动lisp后调用的0参数函数列表。

连接FASL文件

多个fasl文件可以连接成一个文件。单个文件可能更容易分发或安装,加载它可能比加载单个文件稍快(因为它避免了连续打开和关闭每个文件的开销)。

fasl-concatenate output-file fasl-files &key (:if-exists :error)   [功能]

此函数读取列表fasl- files指定的fasl文件,并将它们组合成一个名为output-file fasl 文件。的:if-exists关键字参数被解释为在标准功能open。

加载连接的fasl文件与按指定顺序加载invidual输入fasl文件具有相同的效果。

的pathname-type输出文件和每个输入文件默认为当前平台的FasL的文件类型的(参见特定于平台的文件名约定)。如果任何输入文件具有不同的类型,则将发出错误信号,但是fasl-concatenate否则不会太难以验证输入文件是否是当前平台的真实fasl文件。

浮点数字

在Clozure CL中,Common Lisp类型short-float和single-float被实现为IEEE单精度值; double-float和long-float是IEEE双精度值。在64位平台上,单浮点数是立即值(如fixnums和characters)。

通常启用并检测浮点异常。默认情况下,线程以溢出,除零和启用无效启动,并且舍入模式设置为最接近。这些函数set-fpu-modeget-fpu-mode提供用户对浮点行为的控制。

get-fpu-mode &optional 模式[功能]

返回当前线程的异常使能和舍入模式控制标志的状态。

在没有可选模式参数的情况调用时,此函数返回一个关键字/值对的plist,它描述当前线程的浮点异常启用和舍入模式标志。

如果模式被应用,它应该是关键词之一 :rounding-mode,:overflow,:underflow,:division-by-zero,:invalid,或:inexact。返回相应控制标志的值。

舍入模式

一:nearest, :zero, :positive,或者:negative

溢出,下溢,被零除,无效,不精确

如果t,则发信号通知浮点异常。如果nil,它被掩盖了。

set-fpu-mode &key 舍入模式 溢出 下溢 除零 无效 不精确[功能]

设置当前线程的异常使能和舍入模式控制标志的状态。

舍入模式

如果提供,则必须是以下之一:nearest,:zero,:positive或:negative。

溢出下溢被零除无效不精确

NIL掩盖异常,T表示信号。

将当前线程的异常启用和舍入模式控制标志设置为所提供参数的指示值,并保留与未提供的值相关联的值。

代码覆盖率

概观

在Clozure CL 1.4及更高版本中,代码覆盖率提供了有关生成的代码已执行哪些路径以及哪些路径未执行的信息。对于每个源表单,它可以报告三种可能结果之一:

  • 未涵盖:此表格从未输入。
  • 部分涵盖:此表格已输入,部分部分已执行,部分部分未执行。
  • 完全覆盖:从此表单生成的每一段代码都已执行。

限制

虽然为生成代码的覆盖而收集的信息是完整和精确的,但是返回到源代码形式的映射必然是启发式的,并且在很大程度上取决于宏的行为以及源代码通过编译器转换的路径。不记录变量的源信息,这进一步限制了源映射。在实践中,通常会有足够的信息散布在部分覆盖的函数中,以确定代码中的哪条逻辑路径被采用,哪些不是。如果这不起作用,您可以尝试反汇编以查看编译代码的哪些部分未执行:在反汇编代码中将引用#<CODE-NOTE [xxx] …>其中xxx为NIL,如果后面的代码从未执行过,如果是,则为非NIL。

有时可以通过修改宏来尝试保留更多输入表单而不是解构和重构它们来改善情况。

由于代码覆盖率信息与已编译的函数相关联,因此代码覆盖率信息不适用于加载时顶级表达式。您可以通过创建函数并调用它来解决此问题。也就是说

(progn  (do-this)  (setq that …) …))

做:

(defun init-this-and-that ()  (do-this)  (setq that …)  …)(init-this-and-that)

然后你可以在定义中看到覆盖率信息 init-this-and-that。

用法

为了收集代码覆盖率信息,首先必须重新编译所有代码以包含代码覆盖率检测。如果ccl:*compile-code-coverage* 为true,编译文件将生成代码覆盖检测:

(setq ccl:*compile-code-coverage* t) (recompile-all-your-files)

编译过程将比正常情况慢很多倍,并且fasl文件会大很多倍。

当您执行从已检测的fasl文件加载的函数时,它们将在每次执行时记录覆盖率信息。您可以通过调用ccl:report-coverage 或检查该信息ccl:coverage-statistics。

在记录覆盖范围时,您可以在任意两个时间点之间收集增量覆盖增量。您可以在运行测试套件时执行此操作,以记录每个测试的覆盖范围,例如:

(ccl:reset-incremental-coverage)(loop with coverage = (make-hash-table)      for test in (tests-to-run)      do (run-test test)      do (setf (gethash test coverage) (ccl:get-incremental-coverage))      finally (return coverage))

创建一个哈希表,将测试映射到运行测试时记录的所有coverage的表示。然后可以将此哈希表传递给ccl:report-coverage,ccl:incremental-coverage-svn-matches 或ccl:incremental-coverage-source-matches。

功能和变量

以下功能可用于管理覆盖数据:

report-coverage output-file &key (tags nil) (external-format :default) (statistics t) (html t) [功能]

生成代码覆盖率报告

输出文件

输出索引文件的路径名。

HTML

如果是非nil(默认值),这将生成一个HTML报告,该报告由output-file中的索引文件组成,并且在同一目录中,为当前会话中加载的每个已检测源文件生成一个html文件。

标签

如果是非nil,则应该是将任意键(标记)映射到增量覆盖增量的哈希表。HTML报告将显示标签列表,并允许选择它们的任意子集以显示该子集的覆盖范围的着色和统计信息。

外部格式

控制html文件的外部格式。

统计

如果为非nil(默认值),则使用统计信息摘要生成逗号分隔文件。您可以为statistics参数指定文件名,否则 statistics.csv在output-file目录中创建。有关统计文件中值的说明,请参阅下面的coverage-statistics文档。

如果您已经加载foo.lx64fsl并且 bar.lx64fsl已经运行了一些测试,那么您可以这样做

(report-coverage “/my/dir/coverage/report.html”)

而这将产生report.html,foo_lisp.html并 bar_lisp.html和 statistics.csv所有 /my/dir/coverage/。

reset-coverage[功能]

将所有coverage数据重置为“Not Executed”状态

将所有coverage数据重置为“Not Executed”状态

clear-coverage[功能]

忘记已加载的所有已检测文件。

删除有关已加载哪些已检测文件的信息,因此在加载更多检测文件之前ccl:report-coverage,不会报告任何文件,ccl:save-coverage-in-file也不会保存任何信息。

save-coverage-in-file pathname [功能]

将所有coverage保存到文件中,以便以后还原。

将所有coverage信息保存在文件中,以便稍后恢复覆盖状态。这允许您组合多个运行或在以后的会话中继续。相当于(ccl:write-coverage-to-file (ccl:get-coverage) pathname)。

restore-coverage-from-file pathname[功能]

从文件加载覆盖状态。

恢复先前使用ccl:save-coverage-in-file保存的覆盖率数据,用于在保存和恢复时加载的已检测fasls集。即仅对已在此会话中加载的文件恢复覆盖信息。例如,如果在之前的会话中您已加载 “foo.lx86fsl”然后保存了覆盖信息,则在此会话中您必须”foo.lx86fsl”在调用之前加载相同内容才能 restore-coverage-from-file检索存储的“foo”覆盖信息。相当于(ccl:restore-coverage (ccl:read-coverage-from-file pathname))。

get-coverage[功能]

返回当前coverage数据的快照。

返回当前coverage数据的快照。快照是当前覆盖状态的副本。它可以保存在一个文件中ccl:write-coverage-to-file,作为当前状态恢复ccl:restore-coverage,或与其他快照结合使用ccl:combine-coverage。

restore-coverage snapshot 快照[功能]

将覆盖快照重新安装为当前覆盖状态。

将覆盖快照重新安装为当前覆盖状态。

combine-coverage snapshots 快照[功能]

将多个覆盖快照合并为一个。

获取覆盖快照列表并返回表示所有覆盖数据的并集的新覆盖快照。

write-coverage-to-file snapshot pathname 快照 路径名[功能]

将覆盖范围快照保存在文件中。

将覆盖快照保存在文件中。快照可以加载,ccl:read-coverage-from-file加载和恢复ccl:restore-coverage-from-file。请注意,创建的文件实际上是一个lisp源文件,可以编译以加快加载速度。

rread-coverage-from-file pathname 路径名[功能]

返回保存在文件中的coverage快照。

返回路径名中保存的快照。不影响当前的覆盖状态。pathname可以是先前使用ccl:write-coverage-to-fileor 创建的文件ccl:save-coverage-in-file,也可以是通过编译此类文件创建的fasl的名称。

coverage-statistics[功能]

返回一个ccl:coverage-statistics对象序列,每个源文件一个。

返回一个ccl:coverage-statistics对象序列,每个源文件对应一个,包含与写入统计文件的信息相同的信息report-coverage。为ccl:coverage-statistics对象定义了以下访问器:

coverage-source-file

与此信息对应的源文件的名称

coverage-expressions-total

表达式的总数

coverage-expressions-entered

已输入的源表达式的数量(即至少部分覆盖)

coverage-expressions-covered

完全覆盖的源表达式的数量

coverage-unreached-branches

采取一个分支而一个未采取的条件数

coverage-code-forms-total

代码表单总数。在所有宏扩展和编译器转换和简化之后,代码形式是编译的最后阶段的表达式

coverage-code-forms-covered

已输入的代码表单数

coverage-functions-total

功能总数

coverage-functions-fully-covered

完全覆盖的功能数量

coverage-functions-partly-covered

部分涵盖的功能数量

coverage-functions-not-entered

从未输入的功能数量

reset-incremental-coverage[功能]

重置增量覆盖。

标记记录增量覆盖的起点。请注意,调用此函数不会影响常规覆盖数据(同时调用 ccl:reset-coverage也会重置增量覆盖)。

get-incremental-coverage &key (重置 t)[功能]

返回自上次增量重置以来的覆盖率增量。

返回自上次重置增量coverage以来的覆盖率增量。如果reset为true(默认值),它现在也会重置增量覆盖,以便下一次调用get-incremental-coverage将从此点返回增量。

增量覆盖增量的表示方式与函数返回的完整覆盖范围快照的表示方式不同ccl:get-coverage。增量覆盖使用缩写格式并且缺少完整快照中的某些信息,因此无法传递到记录为接受快照的函数,仅传递给专门记录以接受增量覆盖增量的函数。

incremental-coverage-source-matches collection sources 收集 来源[功能]

查找与源区域相交的增量覆盖增量。

采集

将任意键映射到增量覆盖增量或一系列增量覆盖增量的哈希表。

来源

路径名和/或源注释列表,后者表示文件中的范围。

给定collection其值为增量覆盖增量的哈希表,返回与那些与任何区域相交的增量对应的所有键的列表sources。

例如,如果增量表示测试,则返回的值是覆盖源区域的某些部分的所有测试的列表。

collection也可以是一系列增量,在这种情况下,返回匹配增量的子序列。特别是,您可以通过将其作为单个元素列表传递来测试任何特定增量是否与源相交。

incremental-coverage-svn-matches collection &key (directory (current-directory)) (revision :base)[功能]

查找与特定Subversion版本匹配更改的增量覆盖增量。

采集

将任意键映射到增量覆盖增量或一系列增量覆盖增量的哈希表。

目录

subversion工作目录的路径名。

调整

要与工作目录进行比较的修订,一个整数或其他值,其打印表示适合作为–revision参数传递 给svn。

给定collection其值为增量覆盖增量的哈希表,返回与subversion 中directory自修订版本revision中的任何已更改源相交的那些增量对应的所有键的列表。

例如,如果增量表示测试,则返回的值是可能受更改影响的所有测试的列表。

collection也可以是一系列增量,在这种情况下,返回匹配增量的子序列。特别是,您可以通过将更改作为单个元素列表传入来测试任何特定增量是否受更改影响。

*compile-code-coverage*[变量]

如果为true,则编译仪器功能以收集代码覆盖率信息。

此变量控制是否为代码覆盖率检测功能。在此变量为true时编译的文件将包含代码覆盖率检测。

without-compiling-code-coverage[宏]

不要记录正文中表单的代码覆盖率。

此宏排列,以便正文不记录代码覆盖的内部细节。如果输入它将被视为完全覆盖。Common Lisp宏ASSERT并CHECK-TYPE使用此宏。

解释代码着色

ccl:report-coverage的输出由格式化的源代码组成,其中coverage由colors着色。使用四种颜色:深绿色表示编码为执行每条指令的代码,浅绿色表示已输入但未完全覆盖的表单,红色表示从未输入的表格,页面背景颜色为顶级没有检测的表格。

源颜色是从外部应用的。例如,如果你有

(outer-form … (inner-form …) …)

首先,整个外部形式涂上任何颜色表示外形覆盖,然后内部形式颜色被任何颜色表示内部形式覆盖。这种方法的一个结果是外部形式的每个部分都不是特定在一些可执行的内部形式内部将具有外部形式的覆盖颜色。如果外部表单的语法涉及一些不可执行的表单,或者由于某种原因没有自己的覆盖信息的表单,那么它们将只继承外部表单的颜色,因为它们不会被重新绘制颜色他们自己的。

这种方法可能令人困惑的一种情况是符号。如“限制”部分所述,不会记录变量的覆盖率信息; 因此,变量的着色不会传达有关变量是否被评估的信息 – 该信息不可用,并且变量只是继承了包含变量的表单的颜色。

其他扩展

unwind-protect protected-form {cleanup-form}*        [宏]

确保执行清理表单。

在Clozure CL中,清理表单总是像包装一样执行without-interrupts。要允许中断,请使用 with-interrupts-enabled


Leave a Reply

搜索

分类目录

公 告

本网站学习论坛:

www.zhlisp.com

lisp中文学习源码:

https://github.com/zhlisp/

欢迎大家来到本站,请积极评论发言;

加QQ群学习交流。