Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Types 通用Lisp中的动态类型规范?_Types_Macros_Common Lisp_Typing - Fatal编程技术网

Types 通用Lisp中的动态类型规范?

Types 通用Lisp中的动态类型规范?,types,macros,common-lisp,typing,Types,Macros,Common Lisp,Typing,我知道您可以在编程时声明变量参数的类型: (defun foo (a b) (declare (type integer a b)) 但是,;我希望能够动态地指定类型。我有一个宏,它允许我通过传递args列表来创建a-list(cons单元格列表)。。。例如: (defalist foo (x y z)) --> returns function whose body ~ (list (cons 'x x) (cons 'y y) (cons 'z z)) 我还希望能够动态指定ar

我知道您可以在编程时声明变量参数的类型:

(defun foo (a b) (declare (type integer a b))
但是,;我希望能够动态地指定类型。我有一个宏,它允许我通过传递args列表来创建a-list(cons单元格列表)。。。例如:

(defalist foo (x y z))  
--> returns function whose body ~ (list (cons 'x x) (cons 'y y) (cons 'z z))
我还希望能够动态指定arg的类型,就像在
defun
中那样,但是使用宏以编程方式生成。我尝试过使用declare/declaim,但我一直遇到问题——似乎SBCL需要在编译时指定的实际类型。。。 我希望能够在
defmacro
中执行以下操作:

 (mapcan #'(lambda (arg typ) (declare (type typ arg))) args-list types-list)
最好的方法是什么


谢谢你的帮助

我不太清楚你这里所说的“动态”是什么意思

如果您的意思是希望在运行时动态地提供类型规范(我认为这是“动态”的标准含义),那么您不能使用
declare
(或者如果没有
eval
compile
或其他等效工具,您就不能这样做,让我们不要去那里)。相反,您需要使用
检查类型
typep
或一些相关的东西来动态检查类型。函数定义中使用的
declare
的工作是允许编译器了解函数中类型的一些信息,这可能允许它创建更正确、更仔细、更不仔细、更快速的代码组合(其中哪种应用取决于编译器和编译选项)。为此,必须在编译时知道这些类型

但是,如果您真正想要的是能够在宏定义中声明类型,那么宏扩展将在编译时(或之前)进行,因此,这些类型实际上是静态类型声明:
defalist
将展开info some
defun
表单,您只需向该表单添加合适的
declare

下面是这样一个宏(注意,我不知道你的
defalist
要做什么:这正是我发明的),它允许你指定类型:

(defmacro defalist (name (&rest args/types) &body junk &key
                         (default-type t)
                         (checked-instead
                          ;; use explicit type checks if we're not
                          ;; using a Python-derived compiler.
                          #-(or SBCL CMUCL) t
                          #+(or SBCL CMUCL) nil))
  ;; Each argument should either be a name or (name type).
  (declare (ignore junk))               ;just to get indentation
  (assert (every (lambda (a/t)
                   (or (symbolp a/t)
                       (and (consp a/t)
                            (symbolp (first a/t))
                            (= (list-length a/t) 2))))
                 args/types)
      (args/types)
    "bad arguments ~A" args/types)
  (multiple-value-bind (args types)
      (loop for a/t in args/types
            collect (typecase a/t
                      (symbol a/t)
                      (cons (first a/t)))
            into the-args
            collect (typecase a/t
                      (symbol default-type)
                      (cons (second a/t)))
            into the-types
            finally (return (values the-args the-types)))
    `(defun ,name (,@args)
       ,(if checked-instead
            `(progn
               ,@(loop for a in args and tp in types
                       collect `(check-type ,a ,tp)))
          `(declare ,@(loop for a in args and tp in types
                            collect `(type ,tp ,a))))
       (list ,@(loop for a in args
                   collect `(cons ',a ,a))))))
现在呢

(defalist foo (a b c))
扩展到

(defun foo (a b c)
  (declare (type t a) (type t b) (type t c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
(defun foo (a b c)
  (declare (type integer a) (type integer b) (type integer c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
(defun foo (a b c)
  (declare (type fixnum a) (type float b) (type integer c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
扩展到

(defun foo (a b c)
  (declare (type t a) (type t b) (type t c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
(defun foo (a b c)
  (declare (type integer a) (type integer b) (type integer c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
(defun foo (a b c)
  (declare (type fixnum a) (type float b) (type integer c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
最后

(defalist foo ((a fixnum) (b float) c)
  :default-type integer)
扩展到

(defun foo (a b c)
  (declare (type t a) (type t b) (type t c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
(defun foo (a b c)
  (declare (type integer a) (type integer b) (type integer c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
(defun foo (a b c)
  (declare (type fixnum a) (type float b) (type integer c))
  (list (cons 'a a) (cons 'b b) (cons 'c c)))
一个重要的注意事项:在这个特定的宏中,它定义的函数中的声明肯定会帮助SBCL或CMUCL编译器为您检查参数类型,甚至可能帮助他们推断函数的返回类型(实际上似乎不是这样)。但是,举例来说,它们不会导致它返回的列表以任何不同的方式表示。然而,很容易想象宏有点像这样,其相应的函数在类型声明更有用的地方执行某些操作。即使对于这个函数,您也可以添加一个返回类型的声明,这可能会有所帮助(当然,它可能会帮助SBCL/CMUCL进行更多的类型推断)


如果您没有使用在CMUCL编译器上派生的编译器,那么这样的声明可能会降低代码的安全性。因此,宏尝试检测这种情况,并在这些编译器中用显式检查替换类型声明。这可以用选中的
关键字来手动控制。

宏定义的
定义是什么样子的?因此,实际上您希望生成一个宏定义,其中包含正确的
声明
?这不是一个动态生成的本地宏,并立即应用于参数吗?太棒了,非常感谢!这就是我要找的…动态是一个超载的术语。我的意思是动态的,就像在宏扩展时一样。回答很酷!谢谢