* [2022-09-27 火]
** common lispでの文字列置換2
なんか更新が滞っている。とりあえずこのブログの方針などに
ついては作りながら考えようと思っていたけど、
抜群にSEO対策がなっていない笑
googleのなんとかってのをちょっと設定はしたはずなんだけど。
まぁ、ある意味隠れ家みたいなもんか笑
あと個人ブログにしたんだからlispに限らず好きな事を
書いていきたいんだけど、ちょっと現段階ではまだそういうのが出来てない。
トップページがもうガチにlispって感じだし。
まぁ、そういう事は今はまだいいとして今日のお題は
この前の文字列置換が結局エラーが出たので作り直したという話。
とりあえず、前回作ったものはこれ。
#+BEGIN_SRC lisp
(defun scan (key obj)
(let ((key-len (length key))
(start (search key obj)))
(values start (+ start key-len)))) #+END_SRC
#+BEGIN_SRC lisp
(defun %s (old new obj)
(let ((old-len (length old))
(start (search old obj)))
(concatenate 'string (subseq obj 0 start) new
(let ((rest (subseq obj (+ start old-len))))
(if (< old-len (length rest))
(%s old new rest)
rest))))) #+END_SRC
1つにscanも%sもダブりが多いという事。
という事で、scanを活かして、%sを作り直してみた。
エラーが出た原因だが、%sの処理でキーワードの長さより短くなったら
objectの残りを返す処理をしているが、キーワードの長さより
まだ残っているのに、もうキーワードがobject内に見当たらない時に
エラーが発生していた。
あと、objがnilの時もエラーが発生していた。
そういった諸々の事を解決してみたのが、これ。
#+BEGIN_SRC lisp
(defun scan (key obj)
(let* ((key-len (length key))
(result (search key obj))
(start (when result result)))
(if start
(values start (+ start key-len))
nil)))
(defun %s (old new obj)
(multiple-value-bind (start end)
(scan old obj)
(if start
(let* ((rest (subseq obj end))
(result (%s old new rest)))
(concatenate 'string (subseq obj 0 start) new result))
obj))) #+END_SRC
とここまで書いて、ちょっとscanの処理が冗長じゃないか?と
思って次に訂正。
#+BEGIN_SRC lisp
(defun scan (key obj)
(let ((key-len (length key))
(start (search key obj)))
(when start
(values start (+ start key-len))))) #+END_SRC
という事でリファクタリングバージョンはトータルでいうと、
1行プラスか。
あと%sに関しては常にscanとセットで使わないといけないって
縛りは出来たかな。