Stream Racket:使用宏而不是函数创建流
我目前正在尝试使用宏创建流,如下所示:Stream Racket:使用宏而不是函数创建流,stream,macros,racket,thunk,Stream,Macros,Racket,Thunk,我目前正在尝试使用宏创建流,如下所示: (define-syntax create-stream (syntax-rules (using starting at with increment ) [(create-stream name using f starting at i0 with increment delta) (letrec ([name (lambda (f current delta) (c
(define-syntax create-stream
(syntax-rules (using starting at with increment )
[(create-stream name using f starting at i0 with increment delta)
(letrec
([name (lambda (f current delta)
(cons current (lambda () (name (f (+ current delta) delta)))))])
(lambda () (name f i0 delta)))
]))
但是,当我稍后尝试将以下lambda函数传递给它时,会出现编译错误,该函数表示“lambda:不是标识符、带有默认值的标识符或关键字”
(使用(λ(x)(*x))从5开始以增量2创建流方块)
我怀疑的是,通过尝试在宏中使用lambda,它在Racket中隐藏了实际的lambda函数。如果这是真的,我想知道在不使用lambda的情况下如何创建流,因为据我所知,需要在某个地方有一个函数来创建所述流
这也是一个家庭作业问题,所以我必须使用宏。我创建流的等效函数是:
(define create-stream
(letrec ([name (lambda (f current delta) (cons current (lambda () (name (f (+ current delta) delta)))))])
(lambda () (name f i0 delta))))
我怀疑正在发生的事情是,试图在宏中使用lambda,它在Racket中隐藏了实际的lambda函数
不,那不对
这里的问题是,您在绑定位置使用f
和delta
(lambda(f当前delta))。这意味着在展开(使用(lambda(x)(*x))从5开始以增量2创建流方块)
后,您将得到如下代码:
(lambda ((lambda (x) (* x x)) current 2) ...)
这显然是一个语法错误
您可以通过使用DrRacket中的宏步进器自己看到这一点
修复方法是将标识符重命名为其他名称。例如:
(define-syntax create-stream
(syntax-rules (using starting at with increment )
[(create-stream name using f starting at i0 with increment delta)
(letrec
([name (lambda (f* current delta*)
(cons current (lambda () (name (f* (+ current delta*) delta*)))))])
(lambda () (name f i0 delta)))
]))
这将使您的代码开始运行,但您的代码中还有其他几个bug。因为这是你的家庭作业,我将把它们留给你。你当前的问题基本上归结为这个(坏的)代码 这并不等同于
(定义y 0)
-y
的定义是let绑定的本地定义
解决方案是翻转定义,使letrec
位于define
的本地:
(define name
(letrec (... fn definition ...)
(lambda () (fn i0))))
谢谢,这很有帮助。不过,我遇到了一个新的bug,所以如果您能给我一些建议,我将不胜感激。那么,您对这个问题的理解是什么?你做了什么?好吧,我现在解决这个问题的方法是创建一个帮助函数来创建流,然后让我的宏调用它并将它分配给流名称
(lambda()(f i0))
。据我所知,宏应该能够直接完成这项工作,但我还没有弄清楚如何将它直接包装到我的宏(define sname(lambda()(f i0))
@Chris请用please发布新问题。@Chris您对问题的编辑将使此答案无效。这不是在SO上提问的方式。相反,您应该将此问题恢复到以前的状态,并发布新问题,并带有此问题的链接,以供参考背景。而不是剥离d定义名称
部分,试着保持(定义名称(lambda()(fn i0))
不变,在其后面添加名称
,看看会发生什么。但你真的应该发布一个新的问题。
(define name
(letrec (... fn definition ...)
(lambda () (fn i0))))