Scheme(DrRacket) - 用另一个函数调用广义/抽象函数

时间:2014-12-16 06:09:19

标签: function scheme racket abstraction

作为参考,我使用DrRacket进行Scheme编程。

对于这个问题,我正在使用函数tally-by的通用/抽象函数(不使用高阶函数和/或lambda) tally-by-place-points定义如下:

(define listofCandidates
  (list "Blake" "Ash" "Bob" "Will" "Joey"))

;; Signature: tally-by-place-points: 
;;              list-of-candidates list-of-votes -> list-of-Voting-Tallies
;; Purpose: Consumes a list of candidate names and a list of votes and 
;;          produces a list of voting-tallies.
;;          (Points-Per-Place strategy).
;; Tests:
(check-expect (tally-by-place-points empty empty) empty)
(check-expect (tally-by-place-points listofCandidates listofVotes) 
              (cons (make-voting-tally "Blake" 7)
               (cons (make-voting-tally "Ash" 3)
                (cons (make-voting-tally "Bob" 5)
                 (cons (make-voting-tally "Will" 1)
                  (cons (make-voting-tally "Joey" 2) empty))))))
;; Define:
(define (tally-by-place-points aloc alov)
  (cond
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (total-points-for (first aloc) alov))
                (tally-by-place-points (rest aloc) alov))]))

这就是我提出的(不确定它是否正确)

;; Signature: tally-by: (helper function)
;;              list-of-candidates list-of-votes -> list-of-Voting-Tallies
;; Purpose: Consumes a helper function, a list of candidate names, 
;;          and a list of votes and produces a list of voting-tallies.
;; Define:
(define (tally-by helper aloc alov)
  (cond
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (tally-by helper (first aloc) alov))
                (tally-by helper (rest aloc) alov))]))

我应该注意,这是我所指的帮助函数,total-points-for

;; Signature: total-points-for: string list-of-strings -> number
;; Purpose: Consumes a name and a list of votes and produces the
;;          number of points that the given name has received
;;          using a points-per-place strategy.
;; Tests:
(check-expect (total-points-for "Ash" empty) 0)
(check-expect (total-points-for "Ash" listofVotes) 3)
(check-expect (total-points-for "Blake" listofVotes) 7)
(check-expect (total-points-for "Bob" listofVotes) 5)
(check-expect (total-points-for "Will" listofVotes) 1)
(check-expect (total-points-for "Joey" listofVotes) 2)
(check-expect (total-points-for "Brad" listofVotes) 0)
;; Define:
(define (total-points-for cand alov)
  (cond
    [(empty? alov) 0]
    [(string=? (vote-choice1 (first alov)) cand) 
                        (+ 3 (total-points-for cand (rest alov)))]
    [(string=? (vote-choice2 (first alov)) cand) 
                        (+ 2 (total-points-for cand (rest alov)))]
    [(string=? (vote-choice3 (first alov)) cand) 
                        (+ 1 (total-points-for cand (rest alov)))]
    [else (total-points-for cand (rest alov))]))

我现在必须修改tally-by-place-points函数来调用我刚刚创建的广义/抽象函数tally-by。我应该注意签名,目的和检查期望都是正确的。这是我提出的功能,虽然定义不正确

;; Signature: tally-by-place-points: 
;;              list-of-candidates list-of-votes -> list-of-Voting-Tallies
;; Purpose: Consumes a list of candidate names and a list of votes 
;;          and produces a list of voting-tallies.
;;          (Points-Per-Place strategy).
;; Tests:
(check-expect (tally-by-place-points empty empty) empty)
(check-expect (tally-by-place-points listofCandidates listofVotes) 
              (cons (make-voting-tally "Blake" 7)
               (cons (make-voting-tally "Ash" 3)
                (cons (make-voting-tally "Bob" 5)
                 (cons (make-voting-tally "Will" 1)
                  (cons (make-voting-tally "Joey" 2) empty))))))
;; Define:
(define (tally-by-place-points aloc alov)
  (cond
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (tally-by (first aloc) alov))
                (tally-by (rest aloc) alov))]))

我希望有人能够帮助我处理我的tally-by和修改后的tally-by-place-points函数定义,因为我不确定该怎么做。

2 个答案:

答案 0 :(得分:2)

抽象是纯粹的语法转换!它反过来只是 beta-reduction

..... a .....     ==>     (λa.  ..... a ..... ) a

也就是说,您只需将一些实体用于函数的参数,并将该实体作为函数调用中的参数传递。这样,之前具体的内容现在被概括,变成一个参数,抽象结束:

(define (tally-by-place-points      aloc alov)
  (cond         ; ~~~~~~~~~~~~
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (total-points-for (first aloc) alov))
                           ;       ^^^^^^^^^^^^^^^^^
                (tally-by-place-points (rest aloc) alov))]))

重写为

(define (tally-by   place-points    aloc alov)
  (cond         ;   ~~~~~~~~~~~~
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (place-points     (first aloc) alov))
                           ;       ^^^^^^^^^^^^^^^^
                (tally-by-place-points (rest aloc) alov))]))

以便通话

(tally-by   total-points-for   aloc alov)

相当于之前的电话

(tally-by-place-points         aloc alov)

这当然需要在递归调用中进行整理 - 它也需要进行转换:

(define (tally-by   place-points    aloc alov)
  (cond         ;   ~~~~~~~~~~~~
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (place-points     (first aloc) alov))
                (tally-by   place-points   (rest aloc) alov))]))
                        ;   ~~~~~~~~~~~~

因为我们将(tally-by-place-points ...替换为(tally-by place-points ... - 无处不在。

当然,我们现在可以使用我们想要的任何名称重命名place-points参数(只要名称是唯一的)。

答案 1 :(得分:1)

在逐个积分中,您可以拨打(total-points-for (first aloc) alov)来获取地点积分。在tally-by中,如果您将total-points-for作为参数helper传递,则应该能够完全相同。因此,您需要将total-points-for的引用替换为helper,并在递归时传递帮助:

(define (tally-by helper aloc alov)
  (cond
    [(empty? aloc) empty]
    [else (cons (make-voting-tally (first aloc) 
                                   (helper (first aloc) alov))
                (tally-by helper (rest aloc) alov))]))

在使用tally-by-place-points的{​​{1}} tally-by中,只需使用正确的tally获得的参数调用helper

(define  (tally-by-place-points aloc alov)
  (tally-by total-points-for aloc alov))

顺便说一句,你提到你使用的语言是模棱两可的。从语法中你最有可能在DrRacket中编程。我猜你的第一行是#lang scheme(简称#!scheme)或#!racket,它们是同义词,而不是官方的Scheme语言。对于实际的Scheme语言,您需要使用#!r6rs#!r5rs并根据这些语言进行编程。