Pro mne je cl-loop prostě přenos vlastnosti, na kterou je část lidí zvyklá odjinud.
Hlavní výhodu loopu (v CL) vidím v možnosti rychlé změny.ve fázi zkoumání a testování,
Například idiom
(loop for line = (read-line stream nil nil nil)
while line ...)
by asi šel nahradit něčím jako map-lines, ale do loopu snadno přidám for i from 0 to 10 (nechci při vývoji procházet všech milion řádků), for lineno from 1 (chci u chyby psat cislo radku) nebo unless (zerop (length line)), map-lines by to začalo komplikovat.
V elispu si představím místo read-line třeba re-search-forward, a je fakt že tam je situace asi jiná - (match-string) ani (point) se nemusí předávat.
Po stabilizaci kódu může opravdu být přehlednější vnitřek loopu pojmenovat a volat jiným způsobem, ale to je asi věc vkusu a případ od případu. Koneckonců, ani v CL komunitě není loop oblíben univerzálně.
Jj pomáhá to lidem, co přijdou z jiných jazyků. Navíc to umožňuje napsat všechny "stavy" smyčky na jednom místě.
Ale taky to podle mě protlačili do Common Lispu proto, aby se ukázalo, jak univerzální je jeho makrosystém - prostě přidání i velmi složitých konstrukcí s ním není až tak velký problém (tím neříkám, že bych to makro napsal, ale nějakej základ jo)
to je dobrý příklad
v jiných jazycích se podobně kombinují iterátory. V elispu by to teoreticky šlo také, ale chybí potřebné knihovní funkce.
když si definuji line-seq a take
(setq lexical-binding t)
(iter-defun line-seq ()
(while (< (forward-line) 1)
(iter-yield (thing-at-point 'line t))))
(iter-defun take (n iterator)
(let ((i 0) (it))
(while (and (< i n) (setq it (iter-next iterator)))
(setq i (1+ i))
(iter-yield it))))
tak můžu iterovat prvních 10 řádků
(iter-do (line (take 10 (line-seq))) ........)
V jinych jazycich... Ve standardu Common Lisp the Language, 2nd Edition, circa 1990, se v priloze popisovala struktura series, ktera tohle umoznovala a nabizela, ale do ANSI standardu (1994) se nedostala. Je to stale stahnutelne jako knihovna. Umi to i prevest veci jako
(collect-sum (#Msqrt (subseries (choose-if #'oddp (scan-range :from 0)) 0 10))
na cyklus (kvuli vykonu a spotrebe mista) a je to dost rozsiritelne. Kdyz jsem to zkousel, byl problem prave s delanim malych inkrementalnich zmen (zakomentovat a odkomentovat radek ve for je jednoduche, tohle vyzadovalo menit strukturu), a mozna tam bylo par dalsich nepohodlnosti s reader makry jako #M, uz si moc nepamatuju.
Nějaký náznak loopu už je i pro Clojure udělaný https://github.com/tayssir/cl-loop ale je to skutečně jen alfa.
Zajímavější bude https://github.com/nathell/clj-iter které se snaží o portaci https://common-lisp.net/project/iterate/