* [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))))  ; =>SCAN 
#+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)))))        ; =>%S 
#+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)))                          ; =>SCAN 

  (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)))                          ; =>%S
#+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))))) ; =>SCAN 
#+END_SRC

という事でリファクタリングバージョンはトータルでいうと、
1行プラスか。

あと%sに関しては常にscanとセットで使わないといけないって
縛りは出来たかな。