Scheme 如何驱动此SICP示例函数?

Scheme 如何驱动此SICP示例函数?,scheme,racket,sicp,Scheme,Racket,Sicp,请告诉我如何从SICP正确驱动流提取功能 (define (stream-cons a b) (cons a (delay b))) (define (stream-car s) (car s)) (define (stream-cdr s) (force (cdr s))) (define (stream-withdraw balance amount-stream) (stream-cons balance (stream-withdraw (- balance (stre

请告诉我如何从SICP正确驱动
流提取
功能

(define (stream-cons a b) (cons a (delay b)))
(define (stream-car s) (car s))
(define (stream-cdr s) (force (cdr s)))

(define (stream-withdraw balance amount-stream)
  (stream-cons
   balance
   (stream-withdraw (- balance (stream-car amount-stream)) (stream-cdr amount-stream))))

; Calling stream-withdraw in the following manner raises an exception.
(stream-withdraw 100 (stream-cons 0 0))
; car: contract violation
; expected: pair?
; given: 0

我假设
金额流
应该以不同的方式构造。

尝试使用以下定义:

(define-syntax stream-cons
  (syntax-rules ()
    ((stream-cons head tail)
     (cons head (delay tail)))))

鉴于
stream cons
需要不同的求值规则,它不能作为一个正常的过程来实现-因此,我们使用宏。出于同样的原因,
delay
原语也是一个宏。

流并不是突变状态的真正替代品。这是一种拖延评估的方式

例如:

(定义一到一百万
(let循环((n#e1e6)(acc’())
(如果(零?n)
行政协调会
(循环(-n 1)(cons n acc(()()))
(定义(列出方形lst)
(图(lambda(x)(*x))lst)
(定义(列出双lst)
(图(λ(x)(+x))lst)
(定义(列表sqrt lst)
(地图sqrt lst))
(以(列表sqrt(列表双精度(列表平方1到100万))为例)5)
; ==> (1.4142135623730951 2.8284271247461903 
;      4.242640687119285 5.656854249492381 7.0710678118654755)
如果你看看这里发生了什么,你会发现它在每一步都会列出一个新的百万元素列表,最后只使用前5个结果。流版本:

(定义(流取s n)
(如果(零?n)
'()
(反对)
(数据流获取(数据流cdr s)(-n1()()))
(定义(从n开始的整数)
(流cons n(从(+n1)开始的整数)
(从1开始定义(从1开始的整数));无限的溪流!
(定义(流映射过程流)
(流控(过程(流车流))
(流映射过程(流cdr流)))
(定义(方形流)
(溪流图(λ(x)(*x))溪流)
(定义(双流)
(溪流图(λ(x)(+x))溪流)
(定义(流sqrt流)
(流地图sqrt流))
(取流(取流sqrt(取流二次(取流平方从1开始)))5)
; ==> (1.4142135623730951 2.8284271247461903 
;      4.242640687119285 5.656854249492381 7.0710678118654755)
在这个版本中,在开始第二个元素的平方之前,它将对结果中的第一个元素执行每个步骤,但是程序的结构看起来好像是先执行平方,然后执行双精度等

一种可能是现代的方法,它使用列表,但每个元素的所有步骤都是传感器和发生器

至于保持状态,你不需要流。您可以创建一个递归直到完成的过程:

(让循环((状态“())(输入))
(如果(输入为空?输入)
陈述;完成
(循环(过程输入(输入获取输入)状态)
(输入下一个输入)))
现在我们可以给它一个完全功能化的实现:

(定义输入’(1 2 3 4))
(定义输入获取车辆)
(定义下一个cdr的输入)
(定义输入为空?空?)
(定义过程输入cons)
或者我们可以让它成为一个肮脏的副作用版本:

(定义输入(当前输入端口))
(定义输入获取读取行)
(定义输入下一个值);只需返回港口
(定义输入为空?(λ(x)(eq?(peek字节x)eof));检查是否还有更多内容需要阅读
(定义过程输入cons)

我在SICP中发现流cons必须是一种特殊形式。让我修改我的问题:构建数量流的正确方法是什么?另外,我希望看到在用户输入新的取款时,在后续调用中使用该流的典型方式,即以功能性的方式进行流取款。我仍然看不到使用流避免本地状态的关键因素。谢谢你回答我最初的问题。您能否为OO程序员概述一下如何在一个简单的读取循环中应用流来管理一个人的平衡?我只是不知道函数式编程如何在没有赋值的情况下解决这样的问题。也许是通过创建一个平衡的值流?我对SICP的这一章有点不太了解,但IIRC在书中对此进行了解释。我希望关于streams的这一章能帮助我理解这个问题。不幸的是,未显示平衡流的应用。当你说“余额的价值流”时,我听起来好像有一个流收集取款,但它应该是可变的,不是吗?我真的很困惑。流将记录余额值的整个历史记录,但只有最后一个记录是Current。您如何保留流并使用用户输入的取款扩展它?“这条河是不可变的,不是吗?”阿提拉卡罗利,你问我一个例子,在我的回答的最后,我有一个例子。在该示例中,我没有使用流来说明流不是“保持”/“更新”状态的要求,但是我知道请求用户输入或显示输出是副作用,因此会破坏纯净度。