2017-09-19 121 views
3

如果我有一個接受函數的參數,優化目的的功能,我可以宣佈它是一個function,假設SBCL優化:函數的類型聲明

(defun foo (f) 
    (declare (type function f)) 
    ...) 

不過,我可以更加具體:

(defun foo (f) 
    (declare (type (function (double-float) double-float) f)) 
    ...) 

即告知f將接受一個double-float參數和返回一個double-float值。但是,SBCL似乎能夠對前者進行更好的優化,對於後者,它說它不知道f是否爲fdefinition(嘗試使用(optimize (speed 3))聲明進行編譯以重現)。

所以,我的問題是:

  • 難道我做錯了什麼?特別是如果SBCL只會爲function(function ...)做同樣的事情,我會對它好,但實際上它會變得更糟。或者它應該被認爲是SBCL中的一個錯誤?

  • 函數類型聲明在CL中根據某種原因在優化方面通常是無用的嗎?

SYSINFO:SBCL 1.3.18

+3

我似乎無法在SBCL 1.3.21/Linux上重現此操作。 '(defun foo(f)(declare(type(function(fixnum)fixnum)f))(funcall f 10)''不會給出警告,反彙編與'(function function f)'相同。 SBCL還會檢查給予'(funcall f ...)'的參數是否爲fixnum並且派生出'FOO'返回一個fixnum。 – jkiiski

+0

@jkiiski Windows現在只有1.3.18版本,用1.3.21編譯和檢查 – mobiuseng

回答

1

從SBCL手冊(4.2.3入門現有的程序運行):

一些不正確的聲明只能通過運行時類型檢測 檢查,因爲SBCL編譯器比其他Common Lisp編譯器做更多的 類型推斷,因此不正確的 聲明可以做更多的損害

這是可能的,這就是爲什麼你的函數不與變量的類型聲明包含更糟。

此外:

最常見的問題是變量,其恆定初始值 不匹配類型聲明。錯誤的常量初始值 將始終由編譯時類型錯誤標記,並且一旦找到,它們就是 很容易修復。考慮下面的代碼片段:

(prog (foo) 
    (declare (fixnum foo)) 
    (setq foo ...) 
    ...) 

這裏FOO被賦予零的初始值,但被宣佈爲一個Fixnum。即使從未讀取,變量的初始值也必須與聲明的類型相匹配。有兩種方法可以解決這個問題。更改聲明

(prog (foo) 
    (declare (type (or fixnum null) foo)) 
    (setq foo ...) 
    ...) 

或更改初始值

(prog ((foo 0)) 
    (declare (fixnum foo)) 
    (setq foo ...) 
    ...) 

這是從手冊SBCL(1.4)的最新版本,所以它可能會或可能不會適用於你的情況。