1

在我正在参加的计算机科学课程中,作为家庭作业,我们的任务是处理几个与消息传递有关的不同问题。除了一个,我已经能够解决所有问题,它要求以下内容:

编写一个 mailman 对象工厂(make-mailman),它不接受任何参数并返回一个响应以下消息的消息传递对象:

  • 'add-to-route: 返回一个接收任意数量邮箱对象并将它们添加到 mailman 对象的“路由”的过程</li>
  • 'collect-letters:返回一个过程,该过程接受任意数量的字母对象并收集它们以供将来分发
  • 'distribute:将每个收集到的信件添加到邮递员路线上地址与信件目的地匹配的邮箱中,并返回目的地与路线上任何邮箱不匹配的任何信件的列表(注意:每次通过 'distribute 邮递员对象后,应该没有收集的信件。)

为使代码更容易而给出的一些注释包括:

  • 如果在一个分发轮中将多封信分发到同一个邮箱,则其中任何一封都可能是其消息通过传递'get-latest-message 到邮箱返回的“最新”信件。

  • 没有两个邮箱将具有相同的地址。

  • 任何邮箱或信件都不会多次传递给邮递员。

  • 分发返回的坏信不需要按特定顺序排列。

  • 使用. args接受任意数量参数的语法。

这是我自己能够弄清楚的:

(define (make-mailman)
  (let ((T '()))
    (define (route-adder . mobjects)
      (assoc mobjects T))
    (define (letter-collecter . lobjects)
      (assoc lobjects T))
    (define (add-to-route mobjects)
      (begin (set! T (cons (route-adder . mobjects) T)) 'done))
    (define (collect-letters lobjects)
      (begin (set! T (cons (sort-strings (letter-collecter . lobjects)) T)) 'done))
    (define (dispatch z)
      (cond ((eq? z 'add-to-route) add-to-route)
        ((eq? z 'collect-letters) collect-letters)
        ((eq? z 'distribute) "unsure of what to do here")
        (else "Invalid option")))
    dispatch))

在这里可以给我的任何帮助都将不胜感激,因为我已经尝试查看这个问题一段时间了,但无法从这里弄清楚该怎么做。

4

2 回答 2

3

您的代码有各种混淆。:) 让我们一步一步来。

dispatch位几乎可以:

(define (make-mailman)
 (let ...
  ...
  (define (dispatch msg)                ;; use short but suggestive var names
   (cond 
    ((eq? msg 'add-to-route)    add-to-route)
    ((eq? msg 'collect-letters) collect-letters)
    ((eq? msg 'distribute) 
       ;; "unsure of what to do here" <<-- Distribute the letters, what else?
                                distribute-the-letters)
    (else "Invalid option")))
  dispatch))

对于这样的对象,一个示例调用将是(define ob (make-mailman))然后((ob 'add-to-route) box1 box2 ... boxn)等等。因此add-to-route必须以这种方式定义过程:

(define (make-mailman)
 (let ((self (list '(ROUTE)           ; each mailman has a route, and a mailbag
                   '(MAILBAG))))      ; use suggestive name here (T, what T?)
  ...
  (define (add-to-route . mailboxes)
    (let ((route (assoc 'ROUTE self))) 
      (set-cdr! route
          (append mailboxes           ; there will be no duplicates
            (cdr route)))
      'DONE))

正确的?与字母相同:

  (define (collect-letters . letters)
    (let ((mailbag (assoc 'MAILBAG self)))
      .....
      'DONE))

现在我们可以处理缺失的部分distribute-the-letters

  (define (distribute-the-letters)
    ;; for each letter in my mailbag
    (let* ((mailbag (assoc 'MAILBAG self))
           (mailboxes (cdr (assoc 'ROUTE self)))
           (letters (cdr mailbag)))
      (if (null? letters) ()
        (let loop ((letter  (car letters))
                   (letters (cdr letters))
                   (not-delivered ()))
    ;;   access its address, 
          (let* ((address (letter 'get-address))
            ;; (we assume it supports this interface, 
            ;;   or maybe that's part of a previous assignment)
    ;;     and find a mailbox on my route such that
                 (mbx (find-mailbox address mailboxes)))
    ;;     its address matches the letter's
    ;;     and if so,
             (if .....
    ;;        put that letter into this mailbox: 
               ((mbx 'put-letter) letter)
    ;;            (we assume it supports this interface, 
    ;;             or maybe that's part of a previous assignment)
    ;;     but if not, add letter to the "not-delivered" list
               ..... )
            (if (null? letters)
    ;; having emptied the mailbag, return the "not-delivered" list
              (begin (set-cdr! mailbag nil) not-delivered)
              (loop (car letters) (cdr letters) not-delivered)))))))

我们假设lettermailbox对象都支持消息类型'get-address,它们都返回相同的可比较address类型的对象,并且mailbox对象支持'put-letter消息。

于 2013-05-07T14:46:46.323 回答
2

除了消息功能的细节之外,您似乎已经掌握了它。但是有一些错误:

(route-adder . mobjects)应该是(router-adder objects)和类似的(letter-collector . lobjects)

的使用begin是不必要的。a 的主体(define (func . args) <body> ...)隐式包含在 a 中begin

习惯上你的代码可以写成:

(define (make-mailman)
  (let ((T '()))
    ;; ...
    (lambda (z)
      (case z
        ((add-to-route)    add-to-route)
        ((collect-letters) collect-letters)
        ((distribute)      distribute)
        (else (error "Invalid option"))))))

[但你可能还不知道case…… lambda]

至于解决实际的消息传递功能。您将需要维护一组邮箱,每个邮箱将保存一组信件。一封信可能包含一个地址和一些内容(回信地址的额外信用)。分发行为将检查每封信上的地址并将其存入其邮箱。邮递员需要保留信件(在他的路线收集信件时),直到被指示分发。

为此,您可以从构建较低级别的功能开始,然后使用较低级别来构建实际的消息传递功能。开始像,例如:

(define (make-letter addr content)
  `(LETTER ,addr ,content))
(define letter-addr cadr)
;; ...

(define (make-mailbox addr)
  '(MBOX ,addr))
(define mailbox-letters cddr)
(define (mailbox-letters-add mailbox letter)
  (set-cdr! (cdr mailbox) (cons letter (mailbox-letters mailbox))))

;;...
于 2013-05-05T14:49:24.030 回答