From: Richard Dale Date: 2004-07-10T22:57:29+09:00 Subject: Re: ruby interpreter as mach kernel server (beside bsd) zuzu wrote: > On Thu, 8 Jul 2004 16:57:24 -0400, zuzu wrote: >> >> one important aspect i have neglected to emphasize is the nature of >> flow-based (aka "agent") programming style in ruby. see >> http://www.jpaulmorrison.com/fbp/index.shtml > > oops, i meant "actor"; classic mistake. http://cliki.tunes.org/Actor > http://c2.com/cgi/wiki?ActorsAndFlowBasedProgrammingDiscussion That's interesting - I've just implemented a ruby version of DCOP for the KDE Korundom bindings. DCOP is the equivalent of Cocoa Distributed Objects, rather than Mach tasks/ipc which is much lower level. It occured to me how you could build an actor-like system in ruby DCOP to schedule workflow in C++ apps. All KDE apps have interfaces exposed as DCOP, which gives you cross process introspection, and nice easy to use cross language rpc. You used to write 'Mach Interface Generator' files like xdr to describe the marshalling (is it still the same?), so for ruby you would do that dynamically. But if you're only communicating with other ruby apps that can understand your protocol, it seems a bit limiting. Does RubyCocoa implement Distributed Objects? That seems a better place to start on Mac OS X to me. In Korundum, you define DCOP slots like this: class MyWidget < KDE::PushButton k_dcop 'void mySlot(QString)', 'QPoint getPoint(QString)' def initialize(parent, name) super end def mySlot(greeting) puts "greeting: #{greeting}" end def getPoint(msg) puts "message: #{msg}" return Qt::Point.new(50, 100) end end The 'tag' or unique name for this actor is 'dcopslot/MyWidget/' - the name of the app and the class with the slot. Here is an example of synchronous communication ('slots' are Qt's in process equivalent of DCOP slots): class SenderWidget < PushButton def initialize(parent, name) super connect(self, SIGNAL('clicked()'), self, SLOT('doit()')) end slots 'doit()' def doit() dcopRef = DCOPRef.new("dcopslot", "MyWidget") result = dcopRef.call("QPoint getPoint(QString)", "Hello from dcopcall") puts "result class: #{result.class.name} x: #{result.x} y: #{result.y}" end end Of course in ruby the above call() should really look like this, and use method_missing(): result = dcopRef.getPoint("Hello from dcopcall") Or synchronous communication: class SenderWidget < KDE::PushButton def initialize(parent, name) super Qt::Object::connect(self, SIGNAL('clicked()'), self, SLOT('doit()')) end slots 'doit()' def doit() dcopRef = KDE::DCOPRef.new("dcopslot", "MyWidget") dcopRef.send("mySlot(QString)", "Hello from dcopsend") end end And of course you can send DCOPRef's over DCOP to other KDE programs or actors. The script for the actor's behaviour definition can be just a ruby string instance variable, which is eval'd for the current request in the actor's 'become' method. Each response to a message generates the script to respond to the next message. So the next step is to try and write the factorial example from Gul Agha Actors book in DCOP.. -- Richard