* [2023-03-26 日]
((☔ . 雨) (☁→☼ . くもり 昼前 から 晴れ) (☼☁ . 晴れ 時々 くもり))
** loopのおかしな挙動 :lisp:
unix-cmdのwc関数をいじってた。
まずはちょっとものを見てみよう。
#+BEGIN_SRC lisp
(defun wc (files)
"line word char (in case unix,number means line word byte)"
(dolist (f (directory (merge-pathnames files (pwd))))
(with-open-file (in f :direction :input)
(loop :for l = (read-line in nil nil)
:while l
:count l :into line
:sum (length (split " " l)) :into word
:sum (length l) :into char
:finally (format t "~s~%" (list line word char f)))))) #+END_SRC
loopの最後のfinally節で、*standard-output*に出力している。
シェルでコマンド実行するならそれで問題ないと思う。
しかし、そこで出力した値を使いたい場合が出てきたので、
formatではなくreturnを使ってみたが、うまくいかない。
ところがいろいろといじっていると、loopに何かしらnamedを設定した時は
最後の1行分のreturnは返ってくるようになった。
個人的には全行をreturnしてほしいのだが、
現状この裏技では最後の行だけ。
つまりそれまでの行はfinallyにいかずに値が
捨てられて、最後の行だけfinallyで処理されているという話か。
なるほど、書いてたら見えてきた。出来た。
#+BEGIN_SRC lisp
(defun wc (files)
"line word char (in case unix,number means line word byte)"
(let (result)
(dolist (f (directory (merge-pathnames files (pwd))))
(with-open-file (in f :direction :input)
(loop :for l = (read-line in nil nil)
:while l
:count l :into line
:sum (length (split " " l)) :into word
:sum (length l) :into char
:finally (push (list line word char f) result))))
result))
#+END_SRC
こんな感じか。ちょっとpushがダサい気がしないでもない。
個人的にpushってなぜかあまり使いたくない。
破壊的だからかな?