5

我目前正在阅读《Realm Of Racket》一书,到目前为止我真的很喜欢。但是,在第 4 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),并且是根据分数排序的。”
  • “你知道,winers 是一个吃名单的函数,一次遍历一个记录。当至少有一个其他记录时,它会选择第一个,将其命名为fst,并比较fst和它的前辈的分数。取决于就结果而言,所有获胜记录都已被剔除,否则获胜者必须继续寻找得分相等的球员。”

我想这score>是一个错字。除此之外,我完全理解代码 - 在语法和语义方面。我只是不明白它的实际用途。这是什么,为什么有人想要那个?

4

2 回答 2

5

不幸的是,您显示的代码只是为了向您展示本地定义的工作方式。在同一个示例中,您还会看到(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' 范围内。

例如。如果您尝试(winners ...)在球拍交互窗口中使用,您会得到:

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

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

与球拍捆绑在一起,您将拥有来自书下代码的所有代码racket/collects/realm。有 2 种程序定义,称为winners. 第一个chapter 10和第二个chapter 12

至于代码做什么的答案。代码中有错误,所以我们需要修复它。我的猜测是 score> 比较了两条记录的分数。我猜它应该是这样的:

(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))

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

于 2013-07-21T21:34:36.997 回答
4
(winners (cdr lst) (car lst))

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

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

描述说明列表在应用之前排序winners。这仅在按记录分数的降序排序时才有意义。比递减列表的非递减前缀实际上包含所有得分相等的记录 - 最大的记录。“赢家”。

列表按非递增顺序排序的前提条件应该在那里更清楚和突出地说明。

于 2013-07-21T13:10:27.490 回答