* [2022-09-10 土]
** common lispでの文字列置換 :lisp:
ネットで検索すると、cookbookだかが出てきて、
cl-ppcreでの置換は出来るように出てる。
またここのサイトなんか見てもやはりcommon-lisp
には標準で文字列の置換がないという指摘がある。
[[https://shammerism.hatenadiary.com/entry/20081203/1297535192][Lispには文字列置換関数がない?]]
中を読むと以下のような関数が定義されてる。
#+BEGIN_SRC lisp
(defun replace-all (string part replacement &key (test #'char=))
"Returns a new string in which all the occurences of the part
is replaced with replacement."
(with-output-to-string (out)
(loop with part-length = (length part)
for old-pos = 0 then (+ pos part-length)
for pos = (search part string
:start2 old-pos
:test test)
do (write-string string out
:start old-pos
:end (or pos (length string)))
when pos do (write-string replacement out)
while pos)))
#+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
自分なりにppcreとかと時間を比べてみたら
意外とわずかだが速く出来ていた。
向こうは正規表現対応したり内容的にはより
複雑な事やっているからだろうけど。
先程のreplace-allだが定義の仕方
ちょっと素人には厄介な感じはするし、
自分で作った方が感覚的にはわかりやすいかなと。
ただ見ての通り、再帰を使っているから
大きなファイルとかだとちょっと速度がどうなるか?
とも思う。
ついでにcookbookの方のppcreのscanなんてものも
出ていたので、これも置換とほぼ同じ事やってるなと
すぐ作ってみた。
#+BEGIN_SRC lisp
(defun scan (key obj)
(let ((key-len (length key))
(start (search key obj)))
(values start (+ start key-len)))) #+END_SRC
車輪の再発明は良くないとは言われるけど、
自分で作ったらアルゴリズムが理解出来るから
無駄ではないと思う。
プログラミングをやっていると一口に言っても
こういうように
プログラムを"使う"人とプログラムを"作る"人
では全然意味や質が違ってくると思う。
多分pythonユーザーの多くは前者じゃないかな?
便利なライブラリがいっぱいあるっていうし。
でも、自分はなんかそういうのがつまらないと
感じてしまう時がある。
だから車輪の再発明なんてもんはどんどんやってもいいと思う。