週刊nmosh - Msgpack-RPC

非常に細かいバグを2,3修正。(match)ライブラリでellipsisを使ったマッチが出来なかった問題を修正。
本来の(match)は、

(define x '(1 2 3 4 5))
(match x
       ((1 e ... 5)
        (write e) ;; => (2 3 4)
        (newline)))

のように、...を使ってリストの一部分にマッチ出来る。

MessagePack RPC サポートへの道

nmoshは地味にMessagePackをサポートしているので、MessagePack RPCもいっしょにサポートすることに。
MessagePack RPCを使うことで、RubyPythonで書かれたサーバを簡単に呼び出したりその逆ができる。
たとえば、Rubyで3つの引数を足す"sum"メソッドを次のように定義する:

require 'msgpack/rpc'

class SumHandler
    def sum(arg1 , arg2 , arg3)
        return arg1 + arg2 + arg3
    end
end

server = MessagePack::RPC::Server.new

server.listen("0.0.0.0", 1234, SumHandler.new)
server.run

nmoshからこのサーバを呼び出すためには:

(import (rnrs)(shorten)(nmosh net msgpack rpc)
        (nmosh io core)
        (yuni async))

(seq
  (=> make-msgpack-rpc-client-socket ;; 接続
      "localhost" 1234
      (^[ok? obj]
        ;; On error
        (write (list 'Received: ok? obj))(newline))
      => call) ;; 呼び出し手続きを受け取る
  (display "Connected.\n")
  (=> call 'sum '(1 2 3) => sum) ;; sumメソッドの呼び出し
  (write (list 'sum= (car sum)))(newline))

のように書ける。基本的に非同期処理構文を使うのが前提となっている。
ただ、まだまだ課題がある。

  • 値の受け取り方法

今のところ、nmoshの非同期構文は可変長引数を取るコールバックを書けないという問題がある。

 (=> call 'method (list arg0 arg1 arg2) => ret0 ret1 ...)

のようにellipsisが書けるといいかもしれない。(ちょうど↑のmatchと同じような動作となる)
そもそも、MessagePack RPCでは、RPCの結果をArrayで返すと約束しているわけではないので、decomposeするかどうかの選択もしないといけない。

  • サーバの書かせ方

MessagePack RPCのIDL処理系を書くというアイデアも有ったが非常に面倒そうなので躊躇している。
ただ、MessagePackには文字列とbytevectorの区別がないので、その点はどうにかしたいところ。。
ちなみに、現状では↑のsumをSchemeで書くと:

(import (rnrs)(shorten)(nmosh net msgpack rpc)
        (nmosh io core)
        (yuni async))

(define session 0)
(define (make-session ok?)
  (when ok?
    (set! session (+ 1 session)))
  session)

(seq
  (=> make-msgpack-rpc-server-socket
      "0.0.0.0" 1234
      make-session
      (rpc-server
        session
        ((sum arg0 arg1 arg2)
         (+ arg0 arg1 arg2)))
      => ok? obj)
  (display "Listening...\n"))

...要するにまだまだ工夫の余地がある。
結果を常に1つのオブジェクトかArrayで返すモードと、生のMsgpackオブジェクトを操作するモードの2モードが少なくとも必要。さらに非同期応答をサポートするために、callback手続きを受け取るモードも必要。
方針としては、nmosh同士のRPCやnmoshでサーバを書き他の言語でクライアントを書く時はArray渡しプロトコルが普通になるので、まずはそれで。