First the code:
(define (dolist-choice n A B C)
(if (list? n)
(setq n (dec (length n))))
(eval (if C
(if (zero? $idx) A (= $idx n) B C)
(if (member $idx '(0 n)) A B)
)
)
)
This is a special branching function designed for being used within a DOLIST loop. The function can take up to 4 arguments. The first argument is either the list we are looping through or the integer value of the largest index of the list. If we supply a list then the largest index is found for us. A, B, C are each one or more program statements to be executed. If we have all three then if $idx is 0 A is executed else if $idx is the last index B is executed else if $idx is any other index then C is executed. If only A and B are present then if $idx is the first or last index A is executed else B is. I find this one very handy for the toolbox and it can really clean things up - enjoy!
(dolist(i (sequence 0 9))
(dolist-choice (sequence 0 9)
'(println "first: " i)
'(println "last: " i)
'(println "inner: " i)))
(exit)
; first: 0
; inner: 1
; inner: 2
; inner: 3
; inner: 4
; inner: 5
; inner: 6
; inner: 7
; inner: 8
; last: 9
Nice.
In general case we have (= $idx 0) for first, but we miss something like (= $idx $maxidx) for last repetition in loop. We don't have it, right? So, I'm proposing it. $maxidx cannot be known in while, until ... but it can in dotimes, dolist, dostring, for, doargs and map.
In (dotimes (s N) ...) it would be N. In 'dostring' it would be ambiguous, as only the memory food-print-size is stored, which may be different from the visible length (specially on UTF-8 versions). On all other, newLISP doesn't really know the size until walking through the whole list.