2017-02-04 8 views
1

Пожалуйста, обратите внимание на two-in-a-row*? функции в главе 19.получить, первый - выдержанный-комбинатор

Мой вопрос о (leave '()) в функции get-first хелперов. Обратите внимание, что (waddle l) либо вернет '(), либо атом, который указывает, что список исчерпан или получен из списка.

Без (leave '()) он все равно вернет эти два значения, просто не используйте продолжение leave. Но в книге говорится, что без (leave '()) это плохо, я просто не понимаю, почему.

Большое спасибо.

Другие интересные tread об этой проблеме.

+0

Привет, вопросы на SO должны действительно быть самодостаточными. Вы должны хотя бы объяснить словами, что эта функция должна делать; и, возможно, покажет его ожидаемый выход для ввода образца. –

ответ

1

Так спасибо за примеры НСС. Я просмотрел несколько более простых. Итак, «что в этом плохого?» - без (leave '()) в get-first.

Короткий ответ:
Обратите внимание, что из моего кода
I) leave всегда будут воссозданы каждый раз, когда мы называем get-first или get-next. Он вернется либо к get-first, либо к get-next.
ii) fill будет представлять собой цепочку в зависимости от предыдущего fill, и она всегда будет возвращаться к get-first.

Пример
Входной сигнал: '(1)

Итак, мы начинаем путем оценки get-first на '(1).
я) установить leave
II) начинают (waddle '(1)
III), поскольку 1 представляет собой атом, поэтому установить fill быть продолжением тока. Обратите внимание, если мы используем fill, тогда он пойдет делать (waddle (cdr l)), затем он вернется к get-first. iv) возврат к get-first с использованием leave с возвратным значением 1.

Затем мы переходим к eval (T? 1), который, в свою очередь, будет запускать get-next.
я) установить leave
II) запустить fill
III) начать (waddle '())
IV) возвращают () из waddle, затем вернитесь в get-first.

Примечание
1) Если мы не имеем (leave '(), то get-first вернется '(), то two-in-a-row* возвращение #f. Поэтому мы можем получить тот же ответ, но поведение не то, что мы хотим.
2) Если у нас есть это, то обратите внимание, что leave теперь leave создатель: get-next, поэтому он переводит '() в get-next.
3) При создании более 1 ввода в списке, когда мы создаем fill, он будет создан на основе предыдущего fill, таким образом результат будет цепочкой, зависящей от предыдущего fill.

0

Именование прекращается. Я использовал «yield» для «leave» и «next» для «fill». Я также должен был определить atom? и переписать letcc как call/cc, чтобы он работал в Racket. Вот полный код:

(define two-in-a-row* 
    (letrec ([yield '()] 
      [next '()] 
      [atom? (lambda (x) (and (not (null? x)) 
            (not (pair? x))))] 
      [waddle (lambda (l) 
        (cond [(null? l) '()] 
          [(atom? (car l)) 
          (begin 
           (call/cc (lambda (here2) 
              (set! next here2) 
              (yield (car l)))) 
           (waddle (cdr l)))] 
          [else 
          (begin (waddle (car l)) 
            (waddle (cdr l)))]))] 
      [get-first (lambda (l) 
         (call/cc (lambda (here1) 
            (set! yield here1) 
            (waddle l) 
            (yield '()) ; why is this part needed??? 
            )))] 
      [get-next (lambda() 
         (call/cc (lambda (here3) 
            (set! yield here3) 
            (next 'dummy))))] 
      [T? (lambda (a) 
       (let ([n (get-next)]) (display (list "next:" n)) 
        (and (atom? n) 
         (or (eq? a n) 
          (T? n)))))]) 
    (lambda (l) 
     (let ([a (get-first l)]) 
     (and (begin      (display (list "first:" a)) 
        (atom? a)) 
      (T? a)))))) 

Мы можем увидеть разницу здесь:

(two-in-a-row* '(((7) (b)) c (d))) 
    ; w/out yield() : (first: 7)(next: b)(next: c)(next: d)(first:())#f 
    ; w/ yield() : (first: 7)(next: b)(next: c)(next: d)(next:())#f 
    ; w/ yield #f : (first: 7)(next: b)(next: c)(next: d)(next: #f)(next: #f)#t 

(two-in-a-row* '(((7) (b)) c())) 
    ; w/out yield() : (first: 7)(next: b)(next: c)(first:())#f 
    ; w/ yield() : (first: 7)(next: b)(next: c)(next:())#f 
    ; w/ yield #f : (first: 7)(next: b)(next: c)(next: #f)(next: #f)#t 

(two-in-a-row* '(((7) (b)) b())) 
    ; w/out yield() : (first: 7)(next: b)(next: b)#t 
    ; w/ yield() : (first: 7)(next: b)(next: b)#t 
    ; w/ yield #f : (first: 7)(next: b)(next: b)#t 
+0

Hi @With Ness, отлично !!! Теперь я понимаю, как он работает. Я дам вам кредиты для этого. Я напишу все это в другом ответе. – Ling

+0

@ Lingxiao Рад, что это помогло вам как-то. Это настоящий умник. :) –