MIT Scheme Message Passing 抽象 Mailman 程序 [英] MIT Scheme Message Passing abstraction Mailman procedure

查看:21
本文介绍了MIT Scheme Message Passing 抽象 Mailman 程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前在这里问过一个关于消息传递抽象的问题:MIT Scheme 消息传递抽象

I previously asked a question concerning message passing Abstraction here: MIT Scheme Message Passing Abstraction

问题问我:

Write a mailman object factory (make-mailman) that takes in no parameters and returns 
a message-passing object that responds to the following messages:

'add-to-route: return a procedure that takes in an arbitrary number of mailbox objects 
 and adds them to the mailman object's "route"
'collect-letters: return a procedure that takes in an arbitrary number of letter 
 objects and collects them for future distribution
'distribute: add each of the collected letters to the mailbox on the mailman's route 
 whose address matches the letter's destination and return a list of any letters whose 
 destinations did not match any mailboxes on the route (Note: After each passing of 
 'distribute the mailman object should have no collected letters.)

我之前已经写了 2 个程序作为这个作业的一部分来制作邮箱和制作信件:

I had already written 2 procedures earlier as part of this assignment to make a mailbox and make a letter:

(define (make-letter destination message)
  (define (dispatch x)
    (cond ((eq? x 'get-destination) destination)
          ((eq? x 'get-message) message)
          (else "Invalid option.")))
      dispatch)

(define (make-mailbox address)
  (let ((T '()))
    (define (post letter)
      (assoc letter T))
    (define (previous-post post)
      (if (null? (cdr post)) post (cdr (previous-post post))))
    (define (letter-in-mailbox? letter)
      (if (member (post letter) T) #t #f))
    (define (add-post letter)
      (begin (set! T (cons letter T)) 'done))
    (define (get-previous-post post)
      (if (letter-in-mailbox? post)
          (previous-post post)
          #f))
    (define (dispatch y)
      (cond ((eq? y 'add-letter) add-post)
            ((eq? y 'get-latest-message) (get-previous-post T))
            ((eq? y 'get-address) address)
            (else "Invalid option.")))
        dispatch))

在对我当前的答案做错了什么进行了很好的解释并对我的代码进行了许多必要的更改之后,我被告知我在该代码中遇到的任何问题最好在这个问题中提出.因此,这是建立在我之前的问题之上的代码:

After being given a very good explanation on what my current answer was doing wrong and making many necessary changes to my code, I was told that any problems I have in that code would be better off asked in this question. Therefore, here is the code that builds off my previous question:

(define (make-mailman)
  (let ((self (list '(ROUTE) '(MAILBAG))))
    (define (add-to-route . mailboxes)
      (let ((route (assoc 'ROUTE self)))
        (set-cdr! route (append mailboxes (cdr route))) 
        'DONE))
    (define (collect-letters . letters)
      (let ((mailbag (assoc 'MAILBAG self)))
        (set-cdr! mailbag (append letters (cdr mailbag)))
        'DONE))
    (define (distribute-the-letters)
      (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 ()))
              (let* ((address (letter 'get-address))
                     (mbx (find-mailbox address mailboxes)))
                (if (equal? address letter)
                    ((mbx 'add-post) letter)
                    ((mbx 'add-post) not-delivered))
                (if (null? letters)
                    (begin (set-cdr! mailbag '()) not-delivered)
                    (loop (car letters) (cdr letters) not-delivered)))))))
    (define (dispatch z)
      (cond ((eq? z 'add-to-route) add-to-route)
            ((eq? z 'collect-letters) collect-letters)
            ((eq? z 'distribute) distribute-the-letters)
            (else "Invalid option")))
    dispatch))

本质上,我现在遇到了一个不同的错误,它返回的是分发字母过程作为参数传递给长度,而不是列表.我不知道为什么会返回此错误,因为我认为我正在根据需要传入列表.任何人都可以对发生的事情有所了解吗?任何帮助将不胜感激.

Essentially, I'm running into a different error now that instead returns that the distribute-the-letters procedure is being passed as an argument to length, which is not a list. I do not know why this error is being returned, since I would think that I am passing in the lists as they are needed. Would anyone be able to shed some light on what's going on? Any help will be appreciated.

更新:现在在我的 make-mailman 代码中使用这个过程:

UPDATE: Using this procedure in my make-mailman code now:

(define (find-mailbox address mailbox)
  (if (not (element? address self))
      #f
      (if (element? mailbox self)
          mailbox
          #f)))

推荐答案

你的错误在这里:

(define (distribute-the-letters)
  (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 ()))
        (let* ((address (letter 'get-address))
               (mbx (find-mailbox address mailboxes)))  ;; has to be impl'd

      ;;  (if (equal? address letter)          ;; this makes
      ;;    ((mbx 'add-post) letter)           ;;  no
      ;;    ((mbx 'add-post) not-delivered))   ;;   sense   

          ;; here you're supposed to put the letter into the matching mailbox
          ;; or else - into the not-delivered list
          (if mbox                  ;; NB! find-mailbox should accommodate this
            ((mbox 'put-letter) letter)   ;; NB! "mailbox" should accom'te this
            (set! not-delivered      ;; else, it wasn't delivered
              (cons letter not-delivered)))

          (if (null? letters)
            (begin 
              (set-cdr! mailbag '())       ;; the mailbag is now empty
              not-delivered)                       ;; the final return
            (loop (car letters) 
                  (cdr letters) 
                  not-delivered)))))))

find-mailbox 仍然需要在这里实现.它应该搜索匹配的邮箱,如果没有找到就返回#f,如果找到则返回邮箱对象本身.邮箱"对象必须能够响应 'put-letter 消息并具有地址".信件"对象还必须具有地址"(我们通过调用 (letter 'get-address) 检索这些地址,对于邮箱,我们将调用 (mbox 'get-address)),并且这些地址必须是这样我们才能比较它们是否相等.

find-mailbox still has to be implemented here. It should search for the matching mailbox, and return #f in case it is not found, or return the mailbox object itself if it was found. The "mailbox" objects must be able to respond to 'put-letter messages and have "addresses". The "letter" objects must also have "addresses" (which we retrieve with the call (letter 'get-address), and for mailbox we'd call (mbox 'get-address)), and these addresses must be so that we can compare them for equality.

这意味着信件和邮箱应该是通过与这里定义邮递员相同的过程定义的对象,具有内部过程,以及作为对象本身导出的发送过程.

That means that letters and mailboxes should be objects defined through the same kind of procedure as here the mailman is defined, with internal procedures, and the dispatch procedure exported as the object itself.

这一切都需要进一步实施,或者您可能已经将它们作为先前任务的一部分?

This all needs to be further implemented, or perhaps you have them already as part of some previous assignment?

既然您已经提供了其他定义,让我们看看.

now that you've provided your additional definitions, let's see.

make-letter 看起来不错.一封信支持两种消息:'get-destinationget-message.

make-letter seems OK. A letter supports two messages: 'get-destination and get-message.

make-mailbox 有问题.

(define (make-mailbox address)
  (let ((T '()))
    (define (post letter)
      (assoc letter T))         ;; why assoc? you add it with plane CONS
    (define (previous-post post)
      (if (null? (cdr post))         ;; post == T (11)
          post 
          (cdr (previous-post post)  ;; did you mean (prev-p (cdr post)) ? (12)
          )))
    (define (letter-in-mailbox? letter)        ;; letter == T ???????  (3)
      (if (member (post letter) T) #t #f))
    (define (add-post letter)
      (begin (set! T (cons letter T)) 'done))  ;; added with plane CONS
    (define (get-previous-post post)
      (if (letter-in-mailbox? post)            ;; post == T            (2)
          (previous-post post)        ;; post == T (10)
          #f))
    (define (dispatch y)
      (cond ((eq? y 'add-letter) add-post)
            ((eq? y 'get-latest-message) 
               (get-previous-post T))          ;; called w/ T          (1)
            ((eq? y 'get-address) address)
            (else "Invalid option.")))
        dispatch))

你用 add-post 添加字母,它调用 (set!T (cons letter T)).所以它将每个字母按原样添加到 T 列表中.以后无需使用 assoc 来检索它,它只是列表中的一个元素.调用(member letter T)就可以查看是否在里面.post没有函数执行,应该是(define (post letter) letter).

you add letters with add-post, and it calls (set! T (cons letter T)). So it adds each letter into the T list as-is. No need to use assoc to retrieve it later, it's just an element in a list. Just call (member letter T) to find out whether it's in. post has no function to perform, it should be (define (post letter) letter).

(if (member letter T) #t #f) 在功能上与 (member letter T) 相同.在 Scheme 中,任何非假值都类似于 #t.

(if (member letter T) #t #f) is functionally the same as just (member letter T). In Scheme, any non-false value is like a #t.

您的 previous-post(如果使用 (12) 修复)返回其参数列表的最后一个 cdr 单元格.如果它包含字母(a b c d)(previous-post T) 返回(d).你不是说它是 a 吗?毕竟它处理的消息叫做'get-latest-message.你刚刚用 cons 添加到列表 ls 中的任何东西,都可以通过一个简单的调用来恢复......(什么?).

Your previous-post (if fixed w/ (12) ) returns the last cdr cell of its argument list. If it holds letters (a b c d), (previous-post T) returns (d). Didn't you mean it to be a ? The message it handles is called 'get-latest-message after all. Whatever you just added with cons into list ls, can be gotten back with one simple call to ... (what?).

为什么叫get-latest-message?它会返回一封信,还是那封信中的信息?(这里的消息在一个程序中以两种完全不相关的含义使用;更好地调用字母的内容,也许,letter-contents ??

And why is it called get-latest-message? Does it return a letter, or the message within that letter? (and here the word message is used in two completely unrelated senses in one program; better call letter's contents, maybe, letter-contents ??

最后,我们在主程序中调用了(find-mailbox addressmailboxes),但是你定义了(define (find-mailbox addressmailbox) ....它应该比较(equal? address (mailbox 'get-address)).不需要self,所以这个实用函数可以放在全局范围内.它必须枚举那些邮箱:

Lastly, we call (find-mailbox address mailboxes) in the main program, but you define (define (find-mailbox address mailbox) .... It should compare (equal? address (mailbox 'get-address)). self isn't needed, so this utility function can be put into global scope. And it must enumerate through those mailboxes:

(define (find-mailbox address mailboxes)
  (if (not (null? mailboxes))
    (if (equal? address ((car mailboxes) 'get-address))
      (car ..... )
      (find-mailbox address .... ))))

这篇关于MIT Scheme Message Passing 抽象 Mailman 程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆