我读到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
?
答案 0 :(得分:5)
Common Lisp允许定义类型并声明变量,函数,......的类型。
类型与类无关 - 类也是类型,但类型可以表达更多(如整数范围,数组大小,数组的元素类型,......)。
声明类型可能有很多不同的用途:
因此,使用某些编译器设置(调试,空间,速度,编译速度,安全性......)声明类型的效果不是很简单。 Lisp系统可能会忽略大部分声明或广泛使用它们。效果可能非常不同。在某些编译器设置的组合中,声明类型可能会使代码变慢,而在其他情况下,它可能会使代码更快。
此外,编译器可能会进行一些类型的推断。
简单声明可能如下所示:
(defun add-integer (a b)
(declare (integer a b))
(the integer (+ a b)))
Lisp系统现在可以执行以下一项或多项操作:
a
和b
的运行时检查
整数和+操作的结果实际上是一个
整数(而不是浮点数,比率或复数)实现这一目标的典型编译器设置为:
但确切的设置及其含义可能有所不同,应在Lisp实施手册中记录。
这些类型记录在ANSI Common Lisp Standard中。请参阅Types and Classes。
有关编译器设置,请参阅:SBCL Compiler或LispWorks, The Compiler。
要研究编译类型声明代码的效果,可以使用disassemble和time。
答案 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).