1

私が取っているコンピュータ サイエンス コースでは、宿題として、メッセージ パッシングに関するいくつかの異なる質問を課されました。私は次のことを要求する1つを除くすべてを解決することができました:

(make-mailman)パラメータを取らず、次のメッセージに応答するメッセージ パッシング オブジェクトを返すmailman オブジェクト ファクトリを作成します。

  • 'add-to-route: 任意の数のメールボックス オブジェクトを受け取り、それらを mailman オブジェクトの「ルート」に追加するプロシージャを返します</li>
  • 'collect-letters: 任意の数の文字オブジェクトを受け取り、将来の配布のためにそれらを収集するプロシージャを返します
  • 'distribute: 集められた各手紙を郵便配達員のルート上のメールボックスに追加します。住所は手紙の宛先と一致し、宛先がルート上のどのメールボックスとも一致しなかった手紙のリストを返します (注: 'distribute 郵便配達員オブジェクトを通過するたびに、手紙を集めました。)

コードを簡単にするために与えられた注意事項には、次のものがあります。

  • 1 回の配布ラウンドで複数のレターが同じメールボックスに配布された場合、それらのいずれかが'get-latest-message メールボックスに渡されてメッセージが返される「最新の」レターである可能性があります。

  • 2 つのメールボックスが同じアドレスを持つことはありません。

  • メールボックスまたは手紙が郵便配達員に 2 回以上渡されることはありません。

  • 配布によって返される不良文字は、特定の順序である必要はありません。

  • . 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))and then((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"))))))

[しかし、あなたはまだ知らないかもしれませcaselambda...]

実際のメッセージング機能の解決について。各メールボックスが一連の手紙を保持する一連のメールボックスを維持する必要があります。手紙はおそらく住所といくつかの内容で構成されます (差出人住所の追加クレジット)。配布動作は、各レターのアドレスをチェックし、メールボックスに入れます。郵便配達員は、配布するように指示されるまで (手紙を収集するルート上で) 手紙を保持する必要があります。

このためには、低レベルの機能を構築することから始め、次に低レベルを使用して実際のメッセージ パッシング機能を構築します。たとえば、次のように開始します。

(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 に答える