ardggy's blog

Esc - Meta - Alt - Ctrl - Shift

system-type とバイトコンパイル

init.el を見てると、system-type 変数で分岐をとるケースがあったりするけど、これはコンパイル時には判明してるわけで、実行時に分岐するのはどうかなと思った。

もちろん微々たるものではあるし、使いどころも極めて限られているので、なんでもかんでもやるのはむしろデメリットのほうが大きい。

限られた使いどころというのも (eval-when-compile (if (eq system-type 'darwin) 'XXX 'YYY)) みたいに、式の結果が定数になる場合ぐらいしかなさそうだ。 (when (eval-when-compile (executable-find "hogehoge")) ...) は悪くないかもしれない。

ものは試しで、*scratch* で単純な分岐をするだけの関数を書いてコンパイルしてみる。

(defun sample-compile-time ()
  (eval-when-compile
    (cond ((eq system-type 'darwin) "darwin")
          ((eq system-type 'windows-nt) "windows-nt")))

(sample-compile-time) ; C-j
"darwin"

disassembleバイトコードを書き出せる。

おそらくは定数をはきだすだけになってるはず。

(let ((compiled-code (byte-compile 'sample-compile-time)))
  (disassemble compiled-code (current-buffer)))
nil
byte code:
  args: nil
 interactive: nil
0       constant  "darwin"
1       return                                

予想通り、定数命令におちた。

なお、eval-when-compile でつつまない場合は下のようになった。

byte code:
  args: nil
0       varref    system-type
1       constant  <jump-table-eq (darwin 1 windows 2)>
2       switch    
3       goto      3
6:1     constant  "darwin"
7       return    
8:2     constant  "windows-nt"
9       return    
10:3    constant  nil
11      return    

Disassembly - GNU Emacs Lisp Reference Manual