在Common Lisp中输入变量

时间:2017-05-31 09:05:07

标签: types common-lisp typing typed

我读到CL支持可选输入(因为语言中有这个功能)在很多情况下我会假设allos用于更快的代码,但我似乎找不到任何关于实际编写类型代码的内容。是否可以显式键入代码而不是使用黑客? (例如,#include <iostream> template<class T> struct Switcher { Switcher(T const& value) : value_(value) {} template<class F> auto On(T const& candidate, F&& f) -> Switcher& { if (not satisfied_ and candidate == value_) { satisfied_ = true; f(); } return *this; } template<class F> auto Otherwise(F&& f) { if (not satisfied_) { satisfied_ = true; f(); } } private: T const& value_; bool satisfied_ = false; }; template<class T> auto Switch(T const& value) { return Switcher<T>(value); } int main(int argc) { Switch(argc) .On(1, []{ std::cout << "one arg\n"; }) .On(2, []{ std::cout << "two args\n"; }) .Otherwise([]{ std::cout << "more args\n"; }); } 生成#'vector,有点让我想起JS中的simple-vector强制转换为整数)

或者因为类型实际上是CLOS类(它们是,对吗?)你只需要|0类型的对象,比如#'make-instance

2 个答案:

答案 0 :(得分:5)

Common Lisp允许定义类型并声明变量,函数,......的类型。

类型与类无关 - 类也是类型,但类型可以表达更多(如整数范围,数组大小,数组的元素类型,......)。

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

  • 省略优化代码中的运行时类型检查
  • 在优化代码中生成专门指令
  • 编译时类型检查
  • 优化数据结构的分配
  • 运行时类型检查
  • 文档

因此,使用某些编译器设置(调试,空间,速度,编译速度,安全性......)声明类型的效果不是很简单。 Lisp系统可能会忽略大部分声明或广泛使用它们。效果可能非常不同。在某些编译器设置的组合中,声明类型可能会使代码变慢,而在其他情况下,它可能会使代码更快。

此外,编译器可能会进行一些类型的推断。

简单声明可能如下所示:

(defun add-integer (a b)
  (declare (integer a b))
  (the integer (+ a b)))

Lisp系统现在可以执行以下一项或多项操作:

  1. 忽略声明
  2. 添加ab的运行时检查 整数和+操作的结果实际上是一个 整数(而不是浮点数,比率或复数)
  3. 省略+ operation
  4. 的运行时检查
  5. 为专门的+操作生成代码,该操作仅适用于整数
  6. 进行编译时类型检查
  7. 实现这一目标的典型编译器设置为:

    1. safety = 3
    2. safety = 0
    3. 安全= 0且速度= 3
    4. 但确切的设置及其含义可能有所不同,应在Lisp实施手册中记录。

      这些类型记录在ANSI Common Lisp Standard中。请参阅Types and Classes

      有关编译器设置,请参阅:SBCL CompilerLispWorks, The Compiler

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

答案 1 :(得分:0)

有关性能调整,请参见https://lispcookbook.github.io/cl-cookbook/performance.html

有关编译时类型警告,请参见https://lispcookbook.github.io/cl-cookbook/type.html

您可以提供如下类型提示:

(defun max-with-type (a b)
    (declare (optimize (speed 3) (safety 0)))
    (declare (type integer a b))
    (max a b))

并使用the

(defun do-some-arithmetic (x)
  (declare (optimize (speed 3) (debug 0) (safety 0)))
  (the fixnum (+ x (square x))))

使用声明还将在编译时给出更多类型警告。

可以键入变量:

(declaim (type (string) *name*))
(defparameter *name* "book")

我们可以编写类型((or null string))并使用我们自己的类型(用deftype声明)。

您可以使用declaim或在函数内部使用declare声明函数类型:

(declaim (ftype (function (fixnum) fixnum) add))
;;                         ^^input ^^output [optional]
(defun add (n)
    (+ n  1))

有了这个,我们在编译时得到了不错的类型警告。

如果我们更改函数以错误地返回字符串而不是 fixnum,我们得到警告:

(defun add (n)
    (format nil "~a" (+ n  1)))
; caught WARNING:
;   Derived type of ((GET-OUTPUT-STREAM-STRING STREAM)) is
;     (VALUES SIMPLE-STRING &OPTIONAL),
;   conflicting with the declared function return type
;     (VALUES FIXNUM &REST T).