Common Lisp で関数の戻り値の型を宣言する場所と頻度について混乱しています。私の理解が正しければ、宣言によって提供される情報を使用するために実装は必要ありません。また、情報が使用された場合、効果は明確に定義されておらず、おそらく異なる実装間で一貫していないため、これはベスト プラクティスというよりはむしろベスト プラクティスの問題です。正式な定義。これらに答えようとする場合は、そのことを念頭に置いてください。基本的に、これは私が知りたいことです: 最大の効率を目指していると仮定すると ( (optimize (debug 0) (safety 0) speed)
)、関数の戻り値の型宣言は原則としていつ提供されますか?、コンパイラが最適化に使用できる有用な情報? それは大雑把な質問です。しかし、私が求めているものをよりよく理解するために、いくつかの具体的な質問に分けて考えてみましょう。次の定義が与えられた場合:
(defun foo (a)
(the <type> <form>))
(defun bar (a)
(foo a))
(defun baz (a)
(bar a))
a. コンパイラは への呼び出しを最適化できますかBAZ
、または戻りフォームをで、(一見冗長な)フォームのようにラップする必要がBAR
ありますか? 言い換えれば、コンパイラは私が明示的に言わなくても扱うことを知っていますか?BAZ
THE
FOO
(bar <form>)
(the <type> (bar <form>))
b. 3 つの定義の相対的な順序は (a) の答えに影響しますか?
c. 上記の定義が、3 つの別々の fasl ファイルにコンパイルされた 3 つの別々のソース ファイルで発生した場合、(a) の答えはどのように変わりますか?
d. 以下を考えると:
(let ((var1 (foo <form1>))
(var2 (bar <form2>))
(var3 (baz <form3>)))
<form>*)
コンパイラは、(バインドされたオブジェクト) VAR1
、VAR2
、およびVAR3
の本体内で、明示的な型宣言なしで型を正しく推論できますか?それとも、バインディングの直後にLET
別のフォームを追加する必要がありますか?DECLARE
e. LET
質問 (d) が 3 つの関数が定義されているファイル以外のファイルで発生したと仮定すると、次の宣言はどのような影響を与えるでしょうか。
(declaim (ftype (function (t) <type>) foo bar baz))
ファイルの上部に (d) への回答がありますか?