球拍中的流

问题描述 投票:0回答:5

任何人都可以帮助我更好地理解如何编写流吗?

我知道流是一个无限的值序列,我学习对它们进行编程的方式是将它们表示为一个 thunk,当调用时会产生一对 (1) 序列中的第一个元素和 (2) 一个 thunk表示第二个到无穷大元素的流

例如:

(define powers-of-two
    (letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
        (lambda () (f 2))))

我在这里理解,它只是产生 2 的幂并访问这些,例如调用

(car (powers-of-two))
将导致
2
,调用
(car ((cdr (powers-of-two))))
将导致 4

现在我正在尝试编写一个名为

red-blue
的流,它在字符串
red
blue
之间交替,但我对如何构造它有点困惑

scheme racket
5个回答
13
投票

看起来您在问如何使用 thunk 构建自己的自定义流,其他人已经回答了。为了以防万一,值得注意的是 Racket 内置了一个流库,大多数 Racketeers 都会将其用于流。

这是一个例子:

#lang racket
(require racket/stream)
(define reds (stream-cons "red" reds))
(define red-blues (stream-add-between reds "blue"))

;; show ten of them
(for ([i 10] [e (in-stream red-blues)])
  (displayln e))

7
投票

我写了SRFI-41,它描述了流,提供了实现,并给出了许多示例。那里的流与 SICP 中的流不同,并且以 SRFI 中解释的方式“更好”。


6
投票

为了对Scheme中的流有一个总体的了解,我推荐SICP书中的第§3.5 Streams部分。它将教您解决与流相关的问题(例如问题中的问题)的基本概念。

关于问题中的问题,解决的大致思路如下:

  • 构建两个无限流,一个仅生成字符串
    "red"
    ,另一个
    "blue"
  • 合并两个流,从一个流中获取一个元素,然后从另一个流中获取一个元素(交替),此过程在 SICP 中称为
    interleave

1
投票

我是这方面的新手,但以下解决方案似乎也有效:

 (define red-then-blue
   (letrec ([f (lambda (x) (cons x(lambda ()(f(cond [(string=? x "red") "blue"]
                                              ["red"])))))])
   (lambda () (f "red"))))

0
投票

我发现定义一个 Stream-cons* 宏非常简洁,它将递归地使用多个参数

(define-syntax stream-cons*
  (syntax-rules ()
    [(_ x) x]
    [(_ x rest ...) (stream-cons x (stream-cons* rest ...))]))  

然后简单地定义你的流

(define cyclic (stream-cons* 'red 'green 'blue cyclic))

简单检查

(define (stream-show n str) (stream->list (stream-take str n)))
(stream-show 10 cyclic)
==> '(red green blue red green blue red green blue red)
© www.soinside.com 2019 - 2024. All rights reserved.