unfold function in scheme

守給你的承諾、 提交于 2019-12-12 16:17:36

问题


Goal: implement unfold function using only two arguments.

The arguments:

  • the first argument is f which takes an initial value of some type I and returns nil or a cons pair of two elements (the first of these two is the next element that goes in the list of some type A and the next initial value again of some type I).
  • The second argument is an initial value of some type I and the return is a list of items of type A.

This is what I have so far and I am not sure why it is not working:

(define (descending i)
  (if (= i 0)
    (list)
    (cons i (- i 1))))

(define nil (list))

(define (unfold f init)
  (if (eq? (f init) '())
    (list)
    (cons init (unfold f (f init)))))

(unfold (descending 5))

should evaluate to

'(5 4 3 2 1)

This should be the result but isn't. What am I doing wrong?


回答1:


First, it should be (unfold descending 5). Then f would produce a pair and you would use both components of it,

(define (unfold f init)
  (if (eq? (f init) '())
      (list)
      (cons (car (f init)) (unfold f (cdr (f init))))))

But this has awful computational complexity as it calls (f init) three times per iteration. A humble let binding remedies this.

(define (unfold f init)
  (let ((r (f init)))
    (if (empty? r) ;; instead of (eq? r '())
        (list)
        (cons (car r) (unfold f (cdr r))))))

And a tail recursive form using named let

(define (unfold f init)
  (let loop ((acc empty)
             (state (f init)))
    (if (empty? state)
        (reverse acc)
        (loop (cons (car state) acc)
              (f (cdr state))))))

And using match.

(define (unfold f init)
  (let loop ((acc empty)
             (state (f init)))
    (match state
      ((cons x next)
       (loop (cons x acc)
             (f next)))
      (empty
       (reverse acc)))))


来源:https://stackoverflow.com/questions/9286014/unfold-function-in-scheme

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!