Is there a shorter ⁄ better way of writing the following? There's probably some library that does the conversion but I am wondering if some kind of map or fold could work?
(define (weights-to-range lw)
; '(1 4 6 6 6 6 6) -> (1 5 11 17 23 29 35)
(define (f x lw acc)
(if (null? lw)
acc
(let ([y (+ x (car lw))])
(f y (cdr lw) (append acc (list y))))))
(f (car lw) (cdr lw) (list (car lw))))
In Racket I would probably write it using the
for/fold
list comprehension:It would be even simpler except that, since this supplies two accumulation values to the
fold/fold
--xs
andprev
-- thefor/fold
form is going to return two values. So we need to tuck both into temporary vars usingdefine-values
, before passing the one we care about -- fromxs
-- toreverse
. (The var forprev
is named_
. That's just a convention meaning "ignored", because we don't need it.)Of course, the general idea here is to "fold" a list using a "sliding window" of pairs, with the cumulative result so far available to each step. In your case, the function is
+
, but it could be generalized:With such a
fold-slide
(for lack of a better name) function, you could have written simply:Such a
fold-slide
might be even more useful if it could handle "windows" of any size, not just 2.p.s. It's entirely possible there is some SRFI that does something like this, or a more-elegant way to do it in Racket, that I don't know.