Path: csiph.com!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: tpeplt Newsgroups: comp.lang.lisp,comp.lang.scheme Subject: Re: Reduce of alternating terms Date: Mon, 25 Aug 2025 15:20:02 -0400 Organization: A noiseless patient Spider Lines: 81 Message-ID: <87y0r7yzrx.fsf@gmail.com> References: <108g8jr$348l1$1@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Date: Mon, 25 Aug 2025 19:20:14 +0000 (UTC) Injection-Info: dont-email.me; posting-host="e487bec5e0116d3d4dde57ed2528d8f7"; logging-data="3806921"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Vr8VhsK9EM9qxBLu7PMQbjvgZ0XRqGb4=" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:FZ/DV/ZSsR6RJ9hTNC9bfDJ/b/8= sha1:cMdCIL89uQEeSkyGwcPt8sZj/u0= Xref: csiph.com comp.lang.lisp:60670 comp.lang.scheme:6558 "B. Pym" writes: > Pascal Costanza wrote: > >> On 19/05/2014 22:33, Kay Hamacher wrote: >> > Hi there, >> > >> > I want to map/reduce a vector: >> > >> > (reduce #'+ >> > (map 'vector >> > #'(lambda(x) BODY ) >> > ) >> > ) >> > >> > However, BODY has alternating signs for the >> > terms to be added up (first term is positive, >> > second is negative, third is positive,....). >> > One could definitely do this with some global/state >> > variable in the lambda. >> > >> > But I guess there's a much more elegant >> > alternative in LISP. Any hints? >> >> (defun example (vector) >> (loop for index below (length vector) >> sum (* (svref vector index) >> (- 1 (* (rem index 2) 2))))) >> > > Gauche Scheme > > "!" is similar to "do". > > (define (example vec) > (! (sum + (* x sign) > sign 1 (- sign) > x :across vec) > (not x))) > > (example #(400 2 500 3)) Common Lisp’s ‘loop’ macro also supports iterating over vectors, much as the ‘dolist’ macro does for lists. "The for-as-across subclause": http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_6-1-2-1-5.html This eliminates the need for accessing sequence items through indexing and eliminates the possibility of an off-by-one error. The for-as-equals subclause allows a variable to be set to an initial value and, optionally, then be set to a different value on subsequent iterations. "The for-as-equals-then subclause": http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/sec_6-1-2-1-4.html Using these constructs, the above solution can be written either as: (defun alternating-signs (vector) (loop for item across vector and sign = 1 then (- sign) sum (* item sign))) or, (defun alternating-signs (vector) (loop for item across vector for sign = 1 then (- sign) sum (* item sign))) (alternating-signs #(4 -9 11 -19)) ;;=> 43 -- The lyf so short, the craft so long to lerne. - Geoffrey Chaucer, The Parliament of Birds.