2013-02-27 35 views
1

我想写一些代码,但是我的回复程序有问题。忽略前三个随机三项的程序,但在调用pick-random程序时,问题出在else。下面的代码:一个随机程序

(define earlier-responses '()) 

(define (doctor-driver-loop name earlier-responses) 
    (newline) 
    (write '**) 
    (let ((user-response (read))) 
    (cond 
     ((equal? user-response '(goodbye)) 
     (write-line (list 'goodbye name)) 
     (write-line '(see you next week))) 
     (else 
     (list user-response earlier-responses)      
     (write-line (reply user-response earlier-responses)) 
     (doctor-driver-loop name earlier-responses))))) 

(define (reply user-response earlier-responses) 
    (cond 
    ((= (random-of-three) 0) 
     (append (qualifier) 
       (change-person user-response))) 
    ((= (random-of-three) 1) 
     (hedge)) 
    (else 
     (append (write-line '(earlier you said that)) 
       (pick-random earlier-responses))))) 

(define (random-of-three) 
    (random 3)) 

(define (pick-random lst) 
    (nth (+ 1 (random (length lst))) lst)) 

它强调

  (random (length lst))) lst)) 

它抛出这个错误:

 
    random: contract violation 
    expected: (or/c (integer-in 1 4294967087) pseudo-random-generator?) 
    given: 0 

我不知道这是什么错误意味着或如何解决它...

回答

2

该错误是简单地说明该列表长度是零,并random预计1和4294967之间的值087.在拨打pick-random时通过非空列表。这是发生了什么事情:

(random 0) 

=> random: contract violation expected: (or/c (integer-in 1 4294967087) 
    pseudo-random-generator?) given: 0 

尝试在开始处定义一个非空列表的earlier-responses

2

奥斯卡正确回答你问的问题,但你有,你还没有意识到一个糟糕的错误:你应该进入到COND表达前一次计算的随机数,而不是每个COND子句中重新计算它。用你的方法,你不会以相等的概率选择三种可能性中的每一种。第一选择将被选择约三分之一的时间,第二选择将被选择剩余2/3时间的1/3或2/9,并且第三选择将被选择剩余的4/9的时候。你可能希望所有三种选择以相等的概率发生。

1

我想你知道这是什么时候。

[穿上code-review帽子/]

首先,在我们开始之前别的,您使用的是什么版本的球拍?

我在这里得到了5.2.1,所以我可能有点落后,但nthwrite-line似乎并没有在这里定义函数。我想你想要的是list-refwrite。请注意,list-ref具有不同的参数顺序,并且期望列表中的索引为零。换句话说,就是(list-ref (list 1 2 3) 0) => 1。因此,你很可能想定义pick-random

(define (pick-random lst) 
    (list-ref lst (random (length lst)))) 

也有几个不确定的功能有,我想你在你的程序(hedgequalifierchange-person)其他地方的定义。我会在进一步的评论中忽略这些。


奥斯卡提到,random发生在1到4294967087.的整数,这意味着你要传递一个数字来之前,考虑到这一点。请注意,(random n)似乎返回0(- n 1)之间的整数,因此您不需要自己添加或减去一些东西,以便从列表中获取随机元素。

(define (pick-random lst) 
    (if (null? lst) 
     lst 
     (list-ref lst (random (length lst))))) 

作为user448810提到,你不想重新计算random-of-three,因为这不会给你的正在取得每​​一个选择概率相等。既然你会预先计算它,你可能根本不需要random-of-three函数。

(define (reply user-response earlier-responses) 
    (let ((rand (random 3))) 
    (cond ((= rand 0) 
      (append (qualifier) 
        (change-person user-response))) 
      ((= rand 1) 
      (hedge)) 
      (else 
      (append (write '(earlier you said that)) 
        (pick-random earlier-responses)))))) 

write实际上并不返回任何东西。它只是给REPL打印一些东西,所以reply函数的else子句不能代表你的意思,除非write-linewrite做了一些根本性的不同。

(else 
(append (write '(earlier you said that)) 
     (pick-random earlier-responses))) 

要么你想

(else 
    (write '(earlier you said that)) 
    (write (pick-random earlier-responses))) 

如果你只是想打印输出,或

(else 
    (let* ((res (list '(earlier you said that) (pick-random earlier-responses)))) 
    (write res) 
    res)) 

如果你的意思是什么地方保留以备将来使用的返回值。


下,这可能是最大的错误我看到和最容易计划新手做(所以不要心疼),你不改变earlier-responses任何地方。在doctor-driver-loop

(else (list user-response earlier-responses)      
     (write (reply user-response earlier-responses)) 
     (doctor-driver-loop name earlier-responses)) 

else子句创建一个新的列表与user-response为头部和earlier-responses的尾巴,但是你不对它做任何事。您也不会在下一次致电doctor-driver-loop时传递不同的值。如果你真的想跟踪输入历史,你会想,要看起来像

(else (write (reply user-response earlier-responses)) 
     (doctor-driver-loop name (list user-response earlier-responses))) 

将不太做你似乎什么希望它无论是。以上将始终将一个两元素列表传递给驱动程序循环的下一次迭代;第一个元素是最近的响应,第二个元素是earlier-responses

> (list '(I need a perscription) '((how are you doing?) (hello))) 
((I need a perscription) ((how are you doing?) (hello))) 

> (list '(are you even listening?) '((I need a perscription) ((how are you doing?) (hello)))) 
((are you even listening?) ((I need a perscription) ((how are you doing?) (hello)))) 

你最好什么真正想,如果你希望能够挑选使用pick-random随机响应过去,是所有响应的平面列表。这意味着cons新的回应,而不是list他们。

> (cons '(I need a perscription) '((how are you doing?) (hello))) 
((I need a perscription) (how are you doing?) (hello))) 

> (cons '(are you even listening?) '((I need a perscription) (how are you doing?) (hello))) 
((are you even listening?) (I need a perscription) (how are you doing?) (hello)) 

所以你else条款应

(else (write (reply user-response earlier-responses)) 
     (doctor-driver-loop name (cons user-response earlier-responses))) 
0

(定义随机-4-位数 (foldr相似(λ(N'结果) (利弊N(地图(λ(Y)(如果(> =炔)(ADD1 y)的Y)) 结果))) (地图随机'(10 9 8 7))))