Gre*_*bet 4 lisp clisp syntax-checking sbcl common-lisp
我试图更好地理解如何在不同的lisps中评估S表达式,并希望看到它们将处理有趣的错误表达式.我认为Common Lisp和Scheme是完全不同的语言,但它们的语义是否存在特定的差异,这解释了行为的差异.例如,Lisp-1s和Lisp-2s在行为方面存在可观察到的差异,卫生与非卫生宏观系统也是如此.
我有一个程序,在Scheme和Common Lisp中包含一个无法访问的格式错误的if表达式.
;; foo.scm
(if #t 1 (if))
(display "12")
Run Code Online (Sandbox Code Playgroud)
和Common Lisp版本一样
;; foo.lisp
(if t 1 (if))
(display "12")
Run Code Online (Sandbox Code Playgroud)
chicken并且guile都产生语法错误.
鸡:
% chicken foo.scm
Syntax error: (foo.scm:1) in `if' - pair expected
(if)
Expansion history:
<syntax> (##core#begin (if #t 1 (if)))
<syntax> (if #t 1 (if))
<syntax> (##core#if #t 1 (if))
<syntax> (if) <--
Run Code Online (Sandbox Code Playgroud)
诡计:
% guile foo.scm
...
.../foo.scm:1:9: source expression failed to match any pattern in form (if)
Run Code Online (Sandbox Code Playgroud)
sbcl并且clisp都打印12并且不发出警告.
SBCL:
% sbcl --load foo.lisp
This is SBCL 1.3.11, an implementation of ANSI Common Lisp.
...
12
0]^D
Run Code Online (Sandbox Code Playgroud)
CLISP
% clisp foo.lisp
"12"
Run Code Online (Sandbox Code Playgroud)
Common Lisp的实现:解释器和编译器
在Common Lisp中,代码执行的类型取决于Lisp系统实现的内容以及如何使用它.Common Lisp实现通常有多种方法来执行代码:解释器和一个或多个编译器.即使是单个运行的实现也可能具有该功能,并且允许用户在这些实现之间切换.
解释器:直接从Lisp数据结构执行.它不是像JVM一样的虚拟机代码的解释器.人们不希望解释器在执行期间验证完整的代码树/图.解释器通常只查看它执行的当前顶层表单.
编译器:将Lisp代码编译为C,一些字节代码或机器代码.由于编译器在代码运行之前生成代码,因此它将对所看到的所有代码(可能的异常,请参见底部的注释)进行语法检查.
Toplevel评估:可以使用解释器,编译器或两者的混合.
GNU CLISP既有解释器又有编译器
GNU CLISP中的示例:
LOAD文本文件通常使用解释器:
[1]> (load "test.lisp")
;; Loading file test.lisp ...
;; Loaded file test.lisp
T
Run Code Online (Sandbox Code Playgroud)
解释器不会检测错误,因为它不会检查整个表达式的语法正确性.由于从不使用带有语法错误的else子句,因此解释器永远不会查看它.
CLISP还有一个编译器:
[2]> (compile-file "test.lisp")
;; Compiling file /tmp/test.lisp ...
** - Continuable Error
in #:|1 1 (IF T 1 ...)-1| in line 1 : Form too short, too few arguments: (IF)
If you continue (by typing 'continue'): Ignore the error and proceed
The following restarts are also available:
ABORT :R1 Abort main loop
Run Code Online (Sandbox Code Playgroud)
如您所见,CLISP编译器检测到语法错误并提供明确的错误消息.
SBCL使用编译器,但也有一个解释器
默认情况下,SBCL使用编译器,它将检测错误.对于顶级表单,它在某些表单中使用更简单的评估机制.也可以切换到翻译.
如果您在SBCL中编写一个简单的IF表单,则评估程序不会使用完整编译,也不会捕获错误:
CL-USER> (if t 1 (if))
1
Run Code Online (Sandbox Code Playgroud)
如果在函数定义中编写相同的代码,则会检测到错误,因为默认情况下将编译函数定义:
CL-USER> (defun foo () (if t 1 (if)))
; in: DEFUN FOO
; (IF)
;
; caught ERROR:
; error while parsing arguments to special operator IF:
; too few elements in
; ()
; to satisfy lambda list
; (SB-C::TEST SB-C::THEN &OPTIONAL SB-C::ELSE):
; between 2 and 3 expected, but got 0
;
; compilation unit finished
; caught 1 ERROR condition
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
Run Code Online (Sandbox Code Playgroud)
如果要切换到完整的SBCL解释器,则在定义时不会检测到错误:
CL-USER> (setf *evaluator-mode* :interpret)
:INTERPRET
CL-USER> (defun foo () (if t 1 (if)))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN
FOO
Run Code Online (Sandbox Code Playgroud)
优化和语法检查
请注意,某些优化编译器可能无法检查无法访问的代码的语法.
摘要
在大多数Common Lisp实现中,您需要使用编译器来获取完整的语法警告/错误.
| 归档时间: |
|
| 查看次数: |
345 次 |
| 最近记录: |