Схема (DrRacket) - вызов обобщенной / абстрагированной функции с другой функцией

Для справки я программирую на Scheme с использованием DrRacket.

Для этой проблемы я делаю обобщенную / абстрактную функцию (в которой не используются функции более высокого порядка и / или лямбду), называемую tally-by функции 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 ответа

Решение

В точках подсчета вы звоните (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 который использует tally-by бы просто позвонить tally с аргументом он получил с правильным helper:

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

Кстати, ваше упоминание о том, какой язык вы используете, неоднозначно. Из синтаксиса вы, скорее всего, программируете ракетку в DrRacket. Я думаю, вы первая строка #lang scheme (#!scheme для краткости) или #!racket, которые являются синонимами, а не официальным языком Схемы. Для реального языка Схемы вам нужно использовать #!r6rs или же #!r5rs и программа в соответствии с теми.

Абстракция - это чисто синтаксическая трансформация! Это просто бета-сокращение в обратном порядке:

..... 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 Параметр теперь, с любым именем, которое мы хотим (если имя уникально).

Другие вопросы по тегам