Scheme 使用贴图或折叠将权重转换为范围的更好方法?

Scheme 使用贴图或折叠将权重转换为范围的更好方法?,scheme,racket,fold,higher-order-functions,map-function,Scheme,Racket,Fold,Higher Order Functions,Map Function,是否有一种更短⁄更好的方式来编写以下内容? 可能有一些库进行转换,但我想知道是否有 地图或折叠可以工作吗 (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) (appe

是否有一种更短⁄更好的方式来编写以下内容? 可能有一些库进行转换,但我想知道是否有 地图或折叠可以工作吗

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

在Racket中,我可能会使用
for/fold
列表理解来编写它:

(define (weights-to-range weights)
  (define-values (xs _)
    (for/fold ([xs '()] [prev 0])
              ([weight (in-list weights)])
      (define this (+ prev weight))
      (values (cons this xs) this)))
  (reverse xs))

(require rackunit)
(check-equal? (weights-to-range '(1 4 6 6 6 6 6))
              '(1 5 11 17 23 29 35))
更简单的是,由于这为
fold/fold
--
xs
prev
提供了两个累加值,
for/fold
表单将返回两个值。因此,我们需要使用
define values
将这两个变量塞进临时变量中,然后再将我们关心的变量从
xs
传递到
reverse
。(用于
prev
的变量名为
。这只是一个约定,意思是“忽略”,因为我们不需要它。)


当然,这里的总体思路是使用成对的“滑动窗口”来“折叠”列表,到目前为止,累积结果可用于每个步骤。在您的例子中,函数是
+
,但它可以是通用的:

(define (fold-slide f vs)
  (define-values (xs _)
    (for/fold ([xs '()] [prev 0])
              ([v (in-list vs)])
      (define this (f prev v))
      (values (cons this xs) this)))
  (reverse xs))
使用这样的
折叠幻灯片
(没有更好的名称)功能,您可以简单地编写:

(fold-slide + '(1 4 6 6 6 6 6)
如果这种折叠幻灯片能够处理任何大小的“窗口”,而不仅仅是2个,那么它可能会更有用


p、 我不知道,完全有可能有一些SRFI可以做这样的事情,或者用一种更优雅的方式在球拍中做。有一个累加器,但仍然可以直接生成答案(也就是说,不必累加一个反向答案,然后在最后反向)


我猜输出中的初始0是隐含的?我尝试了一下,得出了这个精确的解决方案。
;; weights-to-range : (listof number) -> (listof number)
;; Returns list of partial sums of input list.
(define (weights-to-range lw0)

  ;; helper : (listof number) number -> (listof number)
  ;; acc is the sum of elements seen so far
  (define (helper lw acc)
    (cond [(null? lw)
           null]
          [else
           (let ([new-acc (+ acc (car lw))])
             (cons new-acc (helper (cdr lw) new-acc)))]))

  (helper lw0 0))