defsubst

IIJ技術研究所 山本和彦
作成:2002/09/05
更新:2002/09/05

defsubst で定義された関数は、 byte compile の際にインライン展開される。 しかし、どういう場合にインライン展開されるのだろう? 早速実験してみよう。

まず、defun で定義された関数が、 byte compile の際にインライン展開されない例を見ておこう。 以下の例では、foo を byte compile しても、 plus2 という関数名が残るので、 plus2 が foo へインライン展開されていないのが分る。

(defun plus2 (x)
  (+ x 2))
(byte-compile 'plus2)
→ #[(x) "^H\301\\\207" [x 2] 2]

(defun foo (lst)
  (plus2 lst))
(byte-compile 'foo)
→ #[(lst) "\301^H!\207" [lst plus2] 2]

次に defsubst がインライン展開されるのを実際に見るために、 plus2 を defsubst で定義して、 foo を byte compile してみる。 plus2 という関数名は消えて、インライン展開されているのか理解できるだろ。

(defsubst plus2 (x)
  (+ x 2))
(byte-compile 'plus2)
→ #[(x) "^H\301\\\207" [x 2] 2]

(defun foo (lst)
  (plus2 lst))
(byte-compile 'foo)
→ #[(lst) "^H\211^Y\302\\)\207" [lst x 2] 3]

plus2 を funcall で呼び出す場合はどうだろう? これも以下のようにインライン展開される。

(defun bar (lst)
  (funcall 'plus2 lst))
(byte-compile 'bar)
→ #[(lst) "^H\211^Y\302\\)\207" [lst x 2] 3]

では、mapcar の第一引数に与えてみるとどうだろう? 明らかに plus2 は関数だと分るはずだが、 以下のようにインライン展開されないようだ。 "'" を "#'" に変更し、関数だと明示しても結果は変らない。

(defun baz (lst)
  (mapcar 'plus2 lst))
(byte-compile 'baz)
→ #[(lst) "\301\302^H\"\207" [lst mapcar plus2] 3]

どうやら defsubst で定義された関数は、 単純に関数として呼び出される場合と、 funcall で呼び出される場合にインライン展開されるようである。