* [2023-03-26 日]
((☔ . 雨) (☁→☼ . くもり 昼前 から 晴れ) (☼☁ . 晴れ 時々 くもり))
./around-Japan-color-2023-03-26.png

** 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)))))) ; =>WC 
#+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))                            ; =>WC 

#+END_SRC

こんな感じか。ちょっとpushがダサい気がしないでもない。
個人的にpushってなぜかあまり使いたくない。
破壊的だからかな?