MIT Scheme Message Passing Abstraction

前端 未结 2 456
不知归路
不知归路 2021-01-23 23:07

In a Computer Science course I am taking, for homework, we were tasked with several different questions all pertaining to message passing. I have been able to solve all but one,

相关标签:
2条回答
  • 2021-01-24 00:10

    Your code has all kinds of mix-ups. :) Let's proceed step by step.

    The dispatch bit is almost OK:

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

    With such objects, a sample call will be (define ob (make-mailman)) and then ((ob 'add-to-route) box1 box2 ... boxn) etc. So add-to-route procedure must be defined this way:

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

    Right? Same with the letters:

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

    Now we can deal with the missing part, 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)))))))
    

    We assume that both letter and mailbox objects support the message type 'get-address to which they both return the same comparable address type of object, and that mailbox objects support 'put-letter message.

    0 讨论(0)
  • 2021-01-24 00:10

    Other than the specifics of the message functionality, it looks like you've nailed it. There are however some errors:

    This (route-adder . mobjects) should be (router-adder objects) and similarly for (letter-collector . lobjects).

    The use of begin is unneeded. The body of a (define (func . args) <body> ...) is implicitly enclosed in a begin.

    Idiomatically your code could be written as:

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

    [but you may not know about case nor lambda yet...]

    As for solving the actual messaging functionality. You are going to need to maintain a set of mailboxes where each mailbox is going to hold a set of letters. A letter will presumably consist of an address and some content (extra credit for a return-address). The distribute behavior will check the address on each letter and deposit it in its mailbox. The mailman will need to hold letters (while on his route collecting-letters) until instructed to distribute.

    For this you might start by building up the lower-levels of the functionality and then using the lower-levels to build up the actual message passing functionality. Starting like, for example:

    (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))))
    
    ;;...
    
    0 讨论(0)
提交回复
热议问题