I would like to know if there is a way to introduce some local variable in a Common Lisp loop
construct, without any kind of auto increment on it - just as, say, a shortcut syntax to avoid using let outside of the loop.
We'll start wit the simples one. If you let loop do something with any of the accumulation words you can just name a binding and it gets created. Here I make the two bindings odds
and evens
since I want both values returned and counting is one of the verbs described in Loop for black belts and of course CLHS loop specification:
(loop :for num :in '(1 3 5 6 3 3)
:counting (oddp num) :into odds
:counting (evenp num) :into evens
:finally (return (values odds evens)))
; ==> 5
; ==> 1
Also described in the documentation the more general way would be to use with
clause:
(loop :with odds := 0 :and evens := 0
:for num in '(1 3 5 6 3 3)
:if (oddp num) :do (incf odds)
:else :do (incf evens)
:finally (return (values odds evens)))
; ==> 5
; ==> 1
You already know of for e = value then new-value
since it steps, but I add it here for completion. Note that the order is important:
(loop :for odds := 0 :then (if (oddp num) (1+ odds) odds)
:for evens := 0 :then (if (evenp num) (1+ evens) evens)
:for num :in '(1 3 5 6 3 3)
:finally (return (values odds evens)))
; ==> 5
; ==> 1
As a last example we have &aux
elements in functions. It creates let*
bindings without let*
and indent. It is often a real alternative:
(defun count-odds (list &aux (odds 0) (evens 0))
(loop :for num in list
:if (oddp num) :do (incf odds)
:else :do (incf evens))
(values odds evens))
Note tat we don't need to use finally
since the altered bindings are available outside of loop
Knowing CL it's probably a couple more I have missed, but these are the ones I use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With