Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define Local Variable in Common Lisp loop

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.

like image 738
Noob Doob Avatar asked Dec 17 '22 17:12

Noob Doob


1 Answers

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.

like image 147
Sylwester Avatar answered Feb 08 '23 02:02

Sylwester