“球拍领域”的奇怪代码示例

时间:2013-07-21 12:55:22

标签: lisp scheme racket

我目前正在阅读“Realet Of Racket”这本书,到目前为止我非常喜欢这本书。但是,在第7章1/2,第74页,有一个代码示例,我只是没有得到。也许我的思绪拒绝解决,因为我正在度假,但是,我根本不知道它做了什么。

(define (winners lst pred)
  (cond
    [(empty? lst) (list pred)]
    [else
      (define fst (first lst))
      (if (score> (record-score pred) (record-score fst))
        (list pred)
        (cons pred (winners (rest lst) fst)))]))

他们在书中没有真正解释它。但是他们提供了一些提示:

  • “该功能的目的是从游戏记录列表中选择第一名的终结者。”
  • “我们有以下形状的结构定义:(结构记录(名称分数))
  • lst 是此类记录的列表,而 pred 就是这样一条记录。的确, 原始列表是(cons pred lst),并根据得分进行排序。“
  • “你明白获奖者是一个吃饭的功能,并且一次只能记录一条记录。当至少有一条记录时,它会选择第一条记录,将其命名为 fst ,以及比较 fst 及其前辈的得分。根据结果,所有获胜记录都已被取消,或者获胜者必须继续搜索得分相等的球员。“

我认为 score> 是一个错字。除此之外,我完全理解代码 - 在语法和语义方面。我只是没有实际使用它。这是什么以及为什么有人想要这个?

2 个答案:

答案 0 :(得分:4)

(winners (cdr lst) (car lst))

lst中生成非减少记录的记录。 pred代表“前任”(在列表中)。我假设score>是一个比较记录分数的程序(即record-score似乎产生记录的得分,score>比较这些得分。

IOW为给定列表lst生成其前缀,使得其中的记录条目的分数处于非递减顺序。

说明指出在应用winners之前列表是排序。只有在按记录分数的减少顺序排序时才有意义。比减少列表的非递减前缀实际上包含所有具有相同分数的记录 - 最大值。 “赢家”。

列表按非递增顺序排序的前提条件应该在中更清楚明确地说明

答案 1 :(得分:4)

不幸的是,您显示的代码只是向您展示本地定义的工作原理。在同一示例中,您还会看到(define sorted-lst (sort lst ...))根本不起作用。

以下是第75页的整个示例代码,其中包含第74页的所有部分:

(define (winning-players lst)
  (define sorted-lst (sort lst ...)) ;; local variable 
  (define (winners lst pred)         ;; locally defined procedure
    (cond
      [(empty? lst) (list pred)]
      [else
       (define fst (first lst))
       (if (score> (record-score pred) (record-score fst))           
           (list pred)           
           (cons pred (winners (rest lst) fst)))]))
  ;; START HERE:
  ;; uses both local variable and the locally defined procedure
  (winners (rest sorted-lst) (first sorted-lst))) 

他们在以下代码中尝试显示的是winning-players之外,您无法访问sorted-list,也无法使用winners过程,因为它隐藏在winning-players中范围。

EG。如果您尝试在球拍互动窗口中使用(winners ...),则会获得:

  

获奖者:未定义;不能引用未定义的标识符

如果你明白你可以继续享受第5章的乐趣:)

与球拍捆绑在一起,你可以获得racket/collects/realm下书中代码的所有代码。有两种称为winners的程序定义。 chapter 10中的第一个和chapter 12中的第二个。

关于代码的答案。代码中存在错误,因此我们需要修复它。我的猜测是得分>比较两个记录的分数。我猜它应该是这样的:

(struct record (name score) #:transparent)
(define (winning-players lst)
  (define (score> e1 e2)  ; defines a new local procedure
    (> (record-score e1)  ; that compares two records 
       (record-score e2)))

  ;; define sorted-list to be lst sorted by score in decreasing order
  (define sorted-lst (sort lst score>))  
  ;; procedure winners reduces the list to the elements 
  ;; that have same score as pred
  (define (winners lst pred)            
    (cond
      [(empty? lst) (list pred)]
      [else
       (define fst (first lst))
       (if (score> pred fst)           ;; changed to work with records
           (list pred)           
           (cons pred (winners (rest lst) fst)))]))
  ;; START HERE:
  ;; uses both local variable and the locally defined procedure
  (winners (rest sorted-lst) (first sorted-lst))) 

(define scores (list (record "John" 10) 
                     (record "Ben" 5) 
                     (record "Mary" 10) 
                     (record "Owen" 2)))  

(winning-players scores) 
; ==> (list (record "John" 10) (record "Mary" 10))

它返回所有分数最高的列表。