2009-01-30 51 views
3

任何Common Lisp(内置)函数是否返回2个以上的值?我知道许多返回2,但我想不出一个返回3.任何Common Lisp函数是否返回3个值?

(我看到这里有关返回超过2个值的评论,并试图想到CL这样做的情况,但可以')

回答

4

有一个get-setf-expansion函数。它返回5个值。

7

decode-universal-time返回九个值。

+0

噢,你说得对。我知道。真。 – Ken 2009-02-09 17:57:33

27

是的,存在这样的功能。下面是在COMMON-LISP封装,只返回三个值功能的完整列表,如SBCL源代码中声明:

COMPILE         required: 3, optional: 0, rest?: NIL 
INTEGER-DECODE-FLOAT     required: 3, optional: 0, rest?: NIL 
COMPILE-FILE       required: 3, optional: 0, rest?: NIL 
GET-PROPERTIES       required: 3, optional: 0, rest?: NIL 
FUNCTION-LAMBDA-EXPRESSION    required: 3, optional: 0, rest?: NIL 
DECODE-FLOAT       required: 3, optional: 0, rest?: NIL 
RENAME-FILE        required: 3, optional: 0, rest?: NIL 

此外,下面的函数返回值更高的恒定数量比三:

DECODE-UNIVERSAL-TIME     required: 9, optional: 0, rest?: NIL 
GET-DECODED-TIME      required: 9, optional: 0, rest?: NIL 

这些函数返回一个可变数目的值,从而有可能多于三个:

NO-APPLICABLE-METHOD     required: 0, optional: 0, rest?: T 
NO-NEXT-METHOD       required: 0, optional: 0, rest?: T 
VALUES         required: 0, optional: 0, rest?: T 

(I've omitted some functions from this list where SBCL does not declare 
a values type explicitly. get-setf-expansion is one of them.) 

列的说明:required是这些函数的返回值的最小数量,optional SBCL认为可能或可能不会返回的固定数量的返回值,rest?表示预期可变数量的值。 (仅macroexpandmacroexpand-1实际使用&可选的,不要问我为什么。)

而只是为了好玩,这里是我以前拿出这些表的源代码:

(do-external-symbols (sym :common-lisp)           
    (when (fboundp sym)               
    (multiple-value-bind (required optional rest)        
     (let ((fun-type (sb-int:info :function :type sym)))      
      (etypecase fun-type             
      (sb-kernel:fun-type             
      (let ((returns              
        (sb-kernel:fun-type-returns fun-type)))      
       (etypecase returns            
       (sb-kernel:values-type           
        (values (length (sb-kernel:values-type-required returns))  
          (length (sb-kernel:values-type-optional returns))  
          (sb-kernel:values-type-rest returns)))     
       (sb-kernel:named-type           
        (if (sb-kernel:named-type-name returns)      
         (values 1 0 t)           
         (values 0 0 nil))))))          
      (t                 
      (values 0 0 t))))             
     (format t                 
       "~A~40Trequired: ~D, optional: ~D, rest?: ~A~%"     
       sym                
       required optional rest))))