正如 uselpa 在评论中所说,解决方案是在最后使用reverse。扩展后,range 的球拍实现与 reverse 的结果非常相似,是您的 gen-iter 函数的结果,除了某些您可能没有考虑过的情况。
range在球拍中的实际实现使用(for/list ([i (in-range start end step)]) i),但是那个扩展成的其实相当于
(reverse
(for/fold ([fold-var null])
([i (in-range start end step)])
(cons i fold-var)))
除了它使用alt-reverse 函数而不是reverse,它使用for/fold/derived 来更好地报告错误。如果你扩展它,它在一些简化后相当于这个(删除不必要的let-values包装器,错误检查等)
(reverse
(let ([start start] [end end] [inc step])
(let for-loop ([fold-var null] [pos start])
(if (if (>= step 0)
(< pos end)
(> pos end))
(let ([i pos])
(let ([fold-var (cons i fold-var)])
(for-loop
fold-var
(+ pos inc))))
fold-var))))
命名的 let 相当于定义一个这样的辅助函数:(在替换一些 lets 并将辅助函数提升到 range 函数之外)
(define (range start end step)
(reverse
(range-reversed null start end step)))
(define (range-reversed fold-var pos end step)
(if (if (>= step 0)
(< pos end)
(> pos end))
(range-reversed
(cons pos fold-var)
(+ pos step)
end
step)
fold-var))
这与您的解决方案仍然不同,因为您的解决方案假定step 是正数,而这个即使step 是负数也有效。如果step 为正,则if 条件将是(< pos end),而不是嵌套的if。
它也使用(< pos end),你使用(>= pos end),但它也会切换 if 情况。如果(< x y) 与(not (>= x y)) 相同,则这等效于您的解决方案,因为(if (not a) b c) 等效于(if a c b)。但是,至少有一种情况我能想到这是不正确的,start 或end 是+nan.0。在这种情况下,球拍的 range 函数将返回一个空列表,而您的解决方案将进入无限循环。