Types 在公共Lisp中键入变量

Types 在公共Lisp中键入变量,types,common-lisp,typing,typed,Types,Common Lisp,Typing,Typed,我读到CL支持可选类型(就像语言中有这个特性一样),我认为在很多情况下,它可以让代码更快,但我似乎找不到任何关于实际编写类型化代码的信息。可以显式地键入代码而不是使用hack吗?(例如,#向量生成一个简单向量,这让我想起JS中的|0强制为整数) 或者,由于类型实际上是CLOS类(它们是,对吗?),您只需将实例设置为类型对象,例如,'integer?公共Lisp允许定义类型并声明变量、函数等的类型 类型独立于类-类也是类型,但类型可以表达更多(如整数的范围、数组的大小、数组的元素类型等) 声明类型

我读到CL支持可选类型(就像语言中有这个特性一样),我认为在很多情况下,它可以让代码更快,但我似乎找不到任何关于实际编写类型化代码的信息。可以显式地键入代码而不是使用hack吗?(例如,
#向量
生成一个
简单向量
,这让我想起JS中的
|0
强制为整数)


或者,由于类型实际上是CLOS类(它们是,对吗?),您只需将实例设置为类型对象,例如,
'integer

公共Lisp允许定义类型并声明变量、函数等的类型

类型独立于类-类也是类型,但类型可以表达更多(如整数的范围、数组的大小、数组的元素类型等)

声明类型可能有很多不同的用途:

  • 忽略优化代码中的运行时类型检查
  • 在优化代码中生成专用指令
  • 编译时类型检查
  • 优化数据结构的分配
  • 运行时类型检查
  • 文件
因此,使用某些编译器设置(调试、空间、速度、编译速度、安全性等等)声明类型的效果不是很简单。Lisp系统可能会忽略很多声明,或者广泛使用它们。效果可能非常不同。在某些组合中,声明类型的编译器设置可能会使代码速度慢得多,而在其他组合中,则可能使代码速度快得多

此外,编译器还可以进行一些类型推断

一个简单的声明可能如下所示:

(defun add-integer (a b)
  (declare (integer a b))
  (the integer (+ a b)))
(defun max-with-type (a b)
    (declare (optimize (speed 3) (safety 0)))
    (declare (type integer a b))
    (max a b))
Lisp系统现在可以执行以下一项或多项操作:

  • 忽略声明
  • 添加
    a
    b
    的运行时检查 整数,并且+运算的结果实际上是 整数(而不是浮点数、定量或复数)
  • 忽略+操作的运行时检查
  • 为专门的+运算生成代码,该运算只对整数有效
  • 执行编译时类型检查
  • 要实现这一点,典型的编译器设置是:

  • 安全系数=3
  • 安全系数=0
  • 安全=0,速度=3
  • 但具体设置及其含义可能有所不同,应记录在Lisp实现手册中

    这些类型记录在ANSI通用Lisp标准中。看

    有关编译器设置,请参见示例:或


    要研究编译类型声明代码的效果,可以使用和。

    进行性能调整,请参阅

    有关编译时类型警告,请参阅

    您可以给出如下类型提示:

    (defun add-integer (a b)
      (declare (integer a b))
      (the integer (+ a b)))
    
    (defun max-with-type (a b)
        (declare (optimize (speed 3) (safety 0)))
        (declare (type integer a b))
        (max a b))
    
    并使用:

    (defun do-some-arithmetic (x)
      (declare (optimize (speed 3) (debug 0) (safety 0)))
      (the fixnum (+ x (square x))))
    
    使用declaim还将在编译时提供更多类型警告

    可以键入变量:

    (declaim (type (string) *name*))
    (defparameter *name* "book")
    
    我们可以组合类型(
    (或空字符串)
    )并使用我们自己的类型(用
    deftype
    声明)

    您可以使用函数内的
    declaim
    declare
    声明函数类型:

    (declaim(ftype(函数(fixnum)fixnum)add))
    ;;                         ^^输入^^输出[可选]
    (defun添加(n)
    (+n1))
    
    有了它,我们在编译时可以得到很好的类型警告

    如果我们将函数更改为错误地返回字符串而不是 fixnum,我们收到一个警告:

    (defun添加(n)
    (格式nil“~a”(+n1)))
    ; 捕获警告:
    ;   ((GET-OUTPUT-STREAM-STRING-STREAM))的派生类型为
    ;     (简单字符串和可选值),
    ;   与声明的函数返回类型冲突
    ;     (值FIXNUM和REST)。
    
    可能
    (declare(type integer var))
    其中
    var
    是绑定到值
    30
    的变量(例如)?类型与CLO是分开的。您可以使用
    声明
    /
    声明
    /
    声明
    来声明变量/函数的类型。对于结构或类插槽,可以使用
    :TYPE
    关键字,对于数组,可以使用
    :ELEMENT-TYPE
    。例如,
    (let((x10))(declare(type integer x))…)
    。声明类型时实际出现的情况取决于实现和优化设置。通常,您需要提高速度以获得优化的代码,或者提高安全性以进行类型检查。类型不是CLOS类/对象。。所有类都有相应的类型,但不是相反。您不能保证代码在使用类型提示时会运行得更快。依我看,这意味着您可以在需要安全/速度提示时编写代码并键入提示,但这样做总是过早的优化谢谢您的详细回答!当我需要编写快速代码时(我想我需要这样做才能说服我叔叔在他的启动项目中使用CL),我会使用你的建议。
    这个
    做了什么?它是否返回一个特定类型的值?它返回一个整数so
    (字符串“Hello”)
    =>字符串,
    (简单向量#(1 2 3))
    =>简单向量等?检查Hyperpec中的。