Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-10-25

Paul Graham氏のユーティリティ その12

| 17:22 | Paul Graham氏のユーティリティ その12 - わだばLisperになる を含むブックマーク はてなブックマーク - Paul Graham氏のユーティリティ その12 - わだばLisperになる

PG氏のユーティリティを読んでみることの12回目。

引き続き、文字列操作系のユーティリティ編です。

Lisp utilities that were not included in On Lisp or ANSI Common Lisp

お題

extruct-lines

暗記で再現

(defun extruct-lines (string &optional (pos 0))
  (if (= pos (length string))
      nil
      (let ((n (linebreak-pos string pos)))
	(if n
	    (cons (nonwhite-substring string pos n)
		  (extruct-lines string (1+ n)))
	    (list (nonwhite-substring string pos (length string)))))))

できた。extruct-paragraphsの兄弟みたいなもの。こっちは、行ごとに一区切りになる様子。

;; 動作
(extruct-lines "夏草や
    兵どもが
 夢の跡")
;=>("夏草や" "兵どもが" "夢の跡") 

お題

extruct-token-if

暗記で再現:間違えた

;; 間違い
(defun extruct-token-if (str sep-test &optional (start 0))
  (let ((p1 (position-if-not sep-test str :start start)))
    (if p1
	(let ((p2 (position-if-not sep-test str :start (1+ p1))))
	  (if p2
	      (cons (subseq str p1 (1- p2))
		    (extruct-token-if str sep-test p2))
	      (list (subseq str p1))))
	nil)))

;; 正解
(defun extruct-token-if (str sep-test &optional (start 0))
  (let ((p1 (position-if-not sep-test str :start start)))
    (if p1
	(let ((p2 (position-if sep-test str :start p1)))
	  (cons (subseq str p1 p2)
		(if p2
		    (extruct-token-if str sep-test p2)
		    nil)))
	nil)))

大分間違えてしまった。セパレータが連続している場合に対応できていなかった。

;; 動作
(extruct-token-if "や   ら   な   い   か" #'white?)
;=> ("や" "ら" "な" "い" "か") 

下準備

(defconstant whitechars '#(#\Space #\Tab #\Newline #\Return))

お題

separated-tokens

暗記で再現

(defun separated-tokens (str sep)
  (mapcar (lambda (tok) (string-trim whitechars tok))
	  (extruct-token-if str (lambda (c) (eql c sep)))))

できた。指定したセパレータで区切って、さらに空白文字をトリミングするというものらしい。

;; 動作
(separated-tokens "Lisperへの100の質問: ,001,   一番好きな戦車は?,  IV号戦車F型" #\,)
;=> ("Lisperへの100の質問:" "001" "一番好きな戦車は?" "IV号戦車F型") 

お題

extruct-tokens

暗記で再現

;; 間違い
(defun extruct-tokens (str &optional (start 0))
  (let ((p1 (position-if #'constituent str :start start)))
    (if p1
	(if (eql (char str p1) #\")
	    (let ((p2 (position #\" str :start (1+ p1))))
	      (if p2
		  (cons (subseq str (1+ p1) p2)
			(extruct-tokens str (1+ p2)))
		  (list (subseq str (1+ p1)))))
	    (let ((p2 (position-if-not #'constituent str :start p1)))
	      (cons (subseq str p1 p2)
		    (if p2
			(extruct-tokens str (1+ p2))
			nil))))
	nil)))

;; 正解
(defun extract-tokens (str &optional (start 0))
  (let ((p1 (position-if #'constituent str :start start)))
   (if p1
       (if (eql (char str p1) #\")
           (if (< p1 (- (length str) 1))
               (let ((p2 (position #\" str :start (1+ p1))))
                 (if (and p2 (< p2 (- (length str) 1)))
                     (cons (string-trim "\"" (subseq str p1 (1+ p2)))
                           (extract-tokens str (1+ p2)))
                     (list (string-trim "\"" (subseq str p1)))))
               nil)
           (let ((p2 (position-if-not #'constituent
                                      str :start p1)))
             (cons (subseq str p1 p2)
                   (if p2
                       (extract-tokens str p2)
                       nil))))
       nil)))

大分間違えた。どうもこの系統は記憶できない…。基本的に空白文字で区切るが、ダブルクオートでクオートされた部分の処理も追加している感じ。

;; 動作
(extruct-tokens "\"foo bar\" bar baz")
;=> ("foo bar" "bar" "baz")

お題

first-token

暗記で再現

(defun first-token (str &optional (start 0))
  (let ((p1 (position-if #'constituent str :start start)))
    (if p1
	(let ((p2 (position-if-not #'constituent str :start p1)))
	  (subseq str p1 p2))
	nil)))

できた。空白文字で囲まれた最初のトークンを切り出すというものの様子。

;; 動作
(first-token "壹 弐 参")
;=>"壹"

雑感

今回で、PG氏の冷蔵庫の残り物的ユーティリティは一通り読み終りました。暗記して転写するというだけですが、ただ眺めるよりはためになっている気はします。