by shigemk2

当面は技術的なことしか書かない

ブロック

;; 最後まで実行される例
(block block1
  (setq a 1)
  (1+ a))				; => 2
;; 脱出
(block block2
  (setq a 1)
  (return-from block2 (+ a 5))		; => 
  "Not reached!")			; => 6

(defun* block-test ()
  1
  (return-from block-test 2)		;関数名をブロック名に指定して脱出
  3)
(block-test)				; => 2

;; defun*やdefmacro*で定義される関数やマクロは、
;; その関数・マクロ名の暗黙のブロックを作る

(defun* positive-plus (x y)
  "正数のみの足し算"
  ;; 正数以外が含まれていたら脱出するための、ガード条件
  (unless (and (< 0 x) (< 0 y))
    (return-from positive-plus nil))
  (+ x y))
(positive-plus 3 6)			; => 9
(positive-plus -1 2)			; => nil

(with-output-to-string
  (dolist (x '(foo bar baz))
    (when (eq x 'baz) (return))		; 3つ目の要素が来たら脱出
    (princ x)))				; => "foobar"
;; ダイナミックスコープの非局所脱出のメカニズム
;; catchはblockと違いダイナミックスコープである。
;; catchが呼ぶ関数の内部でthrowが呼ばれたらcatchの外側へ脱出する
(catch 'tag1
  1
  (throw 'tag1 2)
  3)					; => 2
;; catchの内部関数の中からでも脱出できる
(defun internal ()
  (throw 'tag2 1000)
  "not reached1")
(catch 'tag2
  (internal)
  "not reached2")			; => 1000

P206

Emacs Lispテクニックバイブル

Emacs Lispテクニックバイブル