2011年5月5日木曜日

矢印でメソッドチェイン風に記述する

なんどか似たようなネタでコードを書いている気がします。

矢印シンボルを用いて括弧の数を減らしてみます。矢印の`>'の個数で式を挿入する位置を決定するようにしてみました。

(defun arrow-symbol? (sym)
(when (symbolp sym)
(let ((name (symbol-name sym)))
(and (<= 2 (length name))
(= (+ (count #\- name)
(count #\> name))
(length name))
(string= (sort (copy-seq name) #'char<)
name)))))

(defun arrow-count (sym)
(count #\> (symbol-name sym)))

(defun collect-arrow-clauses (body)
(do ((rest (reverse body))
(result nil))
((null rest) result)
(let ((pos (position-if #'arrow-symbol? rest)))
(when (null pos)
(error "arrow symbol not found"))
(push (reverse (subseq rest 0 (1+ pos))) result)
(setf rest (subseq rest (1+ pos))))))

(defmacro arrow (obj &body body)
(labels
((expand (rest prev)
(if rest
(let ((insert-pos (arrow-count (caar rest))))
(expand
(cdr rest)
(append
(subseq (cdar rest) 0 insert-pos)
(list prev)
(subseq (cdar rest) insert-pos))))
prev)))
(expand (collect-arrow-clauses body) obj)))

;;; 実効
(arrow "afscd"
-> copy-seq
-> sort #'char<
->>> format t "sorted:~A~%")

;;; マクロ展開後のコード
(FORMAT T "sorted:~A~%" (SORT (COPY-SEQ "afscd") #'CHAR<))

;;; 出力
sorted:acdfs

0 件のコメント:

コメントを投稿