• Re: Reduce of alternating terms

    From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp,comp.lang.scheme on Sun Aug 24 23:52:41 2025
    From Newsgroup: comp.lang.scheme

    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))

    ===>
    895

    Given:

    (define-syntax !-aux
    (syntax-rules (<> @ + - cons cdr :in :across :if ! )
    [(_ (:if bool z ...) ((v i u) seen ...) stuff ...)
    (!-aux (z ...)
    ((v i (if bool u v)) seen ...) stuff ...) ]
    [(_ (x :in lst z ...) seen (lets ...) stuff ...)
    (!-aux (x (and (pair? xs)(pop! xs)) <> z ...)
    seen
    (lets ... (xs lst)) stuff ...) ]
    [(_ (x :across vec z ...) seen (lets ...) stuff ...)
    (!-aux (x (and (< i (vector-length v))
    (begin0 (vector-ref v i) (inc! i))) <>
    z ...)
    seen (lets ... (v vec) (i 0)) stuff ...) ]
    [(_ (a b <> z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b b)) stuff ...) ]
    [(_ (a b + z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b (+ 1 a))) stuff ...) ]
    [(_ (a + n z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a 0 (+ n a))) stuff ...) ]
    [(_ (a b - z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b (- a 1))) stuff ...) ]
    [(_ (a cons b z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a '() (cons b a))) stuff ...) ]
    [(_ (a b cdr z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b (cdr a))) stuff ...) ]
    [(_ (a b c z ...) (seen ...) stuff ...)
    (!-aux (z ...) (seen ... (a b c)) stuff ...) ]
    [(_ (a b) (seen ...) stuff ...)
    (!-aux () (seen ... (a b)) stuff ...) ]
    [(_ (a) (seen ...) stuff ...)
    (!-aux () (seen ... (a '())) stuff ...) ]
    ;;
    [(_ () seen lets a b c ! action ...)
    (!-aux () seen lets (a b c) #t (action ...)) ]
    [(_ () seen lets a b ! action ...)
    (!-aux () seen lets (a b) #t (action ...)) ]
    [(_ () seen lets a ! action ...)
    (!-aux () seen lets a #t (action ...)) ]
    ;;
    [(_ () ((a b c) z ...) lets bool)
    (!-aux () ((a b c) z ...) lets bool a) ]
    [(_ () ((a b c) z ...) lets bool @)
    (!-aux () ((a b c) z ...) lets bool (reverse a)) ]
    [(_ () seen lets bool @ result stuff ...)
    (!-aux () seen lets bool (reverse result) stuff ...) ]
    [(_ () seen lets bool (what @ x z ...) stuff ...)
    (!-aux () seen lets bool (what (reverse x) z ...) stuff ...) ]
    [(_ () seen lets bool (what x @ y z ...) stuff ...)
    (!-aux () seen lets bool (what x (reverse y) z ...) stuff ...) ]
    [(_ () ((a b c) z ...) lets 0 stuff ...)
    (!-aux () ((a b c) z ...) lets (= 0 a) stuff ...) ]
    [(_ () seen lets bool result stuff ...)
    (let lets (do seen (bool result) stuff ...)) ]
    ))
    (define-syntax !
    (syntax-rules ()
    [(_ specs bool stuff ...)
    (!-aux specs () () bool stuff ...) ]
    ))
    --
    [T]he problem is that lispniks are as cultish as any other devout group and basically fall down frothing at the mouth if they see [heterodoxy].
    --- Kenny Tilton
    The good news is, it's not Lisp that sucks, but Common Lisp. --- Paul Graham --- Synchronet 3.21a-Linux NewsLink 1.2
  • From tpeplt@tpeplt@gmail.com to comp.lang.lisp,comp.lang.scheme on Mon Aug 25 15:20:02 2025
    From Newsgroup: comp.lang.scheme

    "B. Pym" <Nobody447095@here-nor-there.org> 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 LisprCOs rCylooprCO macro also supports iterating over
    vectors, much as the rCydolistrCO 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.
    --- Synchronet 3.21a-Linux NewsLink 1.2