麻省理工学院计划消息传递抽象

时间:2013-05-05 01:14:33

标签: scheme

在我正在学习的计算机科学课程中,为了完成家庭作业,我们承担了几个与消息传递相关的不同问题。我已经能够解决除了一个之外的所有问题,其中包括以下内容:

  

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

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

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

  • 如果在一个分发回合中将多个字母分配到同一个邮箱,则为任何一个 它们可能是“最新”的字母,其消息是通过'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))

我可以在这里获得任何帮助,因为我已经尝试了一段时间来解决这个问题,并且无法从这里弄清楚该怎么做。

2 个答案:

答案 0 :(得分: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类型的对象,{{1}对象支持mailbox消息。

答案 1 :(得分:2)

除了消息功能的细节之外,看起来你已经钉了它。但是有一些错误:

(route-adder . mobjects)应为(router-adder objects)(letter-collector . lobjects)也应如此。

不需要使用begin(define (func . args) <body> ...)的正文隐含在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))))

;;...