用无限流替换符号表达式

时间:2014-11-30 14:50:05

标签: functional-programming scheme lisp

我试图用给定的无限流替换给定的符号表达式。 例如,考虑2:

的无限乘法流
(define doubles
  (cons-stream 1 (s-map (lambda (x) (* x 2)) doubles)))

并假设我定义流的函数是正确的。

现在,当我调用我的方法替换符号表达式时,我得到以下内容:

(replace '((a . b) . (c . d)) doubles)
   --> ((1 . 1) 1 . 1)

请注意,我的递归调用只能用无限流的'start'替换我的表达式,即该方法无法跟踪何时使用流的“剩余”部分。

正确的输出应该是:

  

- > ((1.2)4。8)

我目前的代码如下;

(define (replace s str)   (cond ((null? s) '())
        ((atom? s) (head str))
        (else (cons (replace (car s) str)
                    (replace (cdr s) str)))))

那么我的问题就是;我怎么能在调用我的方法recursivley时穿过流? 提前谢谢。

编辑:

我尝试使用其他方法计算剩余流:

(define (replace s str)
  (cond ((null? s) '())
        ((atom? s) (head str))
        (else (cons (replace (car s) (get-stream s str))
                    (replace (cdr s) (get-stream s str))))))

(define (get-stream s str)
  (cond ((null? s) '())
        ((atom? s) (tail str))
        (else (get-stream (cdr s) str))))

这将返回一个新输出:

---> ((4 . 4) 4 . 4)

1 个答案:

答案 0 :(得分:0)

你需要改变str,否则它会继续返回第一个元素。例如,使用set!语句:

(define (replace s str)
  (let loop ((s s))
    (cond ((null? s) s)
          ((pair? s) (cons (loop (car s)) (loop (cdr s))))
          (else      (begin0 
                       (stream-first str)
                       (set! str (stream-rest str)))))))

然后

> (replace '((a . b) . (c . d)) doubles)
'((1 . 2) 4 . 8)

另请参阅我对previous question的评论。

另外,请注意输入结构中没有null,因此测试永远不会产生真实。

编辑这是标准Racket中没有set!的版本,应该很容易移植到R5RS:

(define (replace s str)
  (define-values (res _)
    (let loop ((s s) (str str))
      (cond ((null? s) (values s str))
            ((pair? s) (define-values (res1 str1) (loop (car s) str))
                       (define-values (res2 str2) (loop (cdr s) str1))
                       (values (cons res1 res2) str2))
            (else      (values (stream-first str) (stream-rest str))))))
  res)