Shammer's Philosophy

My private adversaria

with-open-passive-socket 改 ver 20110706

with-open-passive-socket 改 ver 20110703 - Shammerismでは、呼出側でメインの処理を記述する際に progn を記述する必要があったが、その記述をマクロ側に吸収したバージョン。open-socket-server は version 20110703 から変更なし。

(defmacro with-open-passive-socket (&rest body)
  (let ((server-symbol-value (caar body))
	(server-listen-addr (cadar body))
	(server-listen-port (caddar body))
	(main-body (let ((temp-body (list 'progn)))
		     (dolist (x (cdr body))
		       (setf temp-body (append temp-body (list x))))
		     temp-body)))
    `(let ((,server-symbol-value (open-socket-server ,server-listen-addr ,server-listen-port)))
       (unwind-protect
	    (when ,server-symbol-value
	      ,main-body)
	 (unless (null ,server-symbol-value)
	   (format t "Close server socket...~%")
	   (close-server-socket ,server-symbol-value))))))

使用する側は以下のように記述する。

(with-open-passive-socket (server addr port)
  (let* ((client (accept-client-socket server))
         (stream (make-socket-stream client)))
    (do ()
        (nil)
      (let ((line (read-line stream nil 'eof)))
        (if (eql line 'eof)
            (return)
           (format t "~A~%" line))))
    ...

server というのは、その後のメイン処理で使用される server-socket のシンボルになる。
addr は、listen-addr のことで、port は listen-port のこと。with-open-passive-socket の引数として渡される最初の括弧だけが特殊な用途で、2 つ目以降の括弧は全てメインの処理に変換される。