From: "Christoffer Lernö" Date: 2007-03-15T15:13:38+09:00 Subject: Re: Anyone playing with higher order messaging in ruby? On Mar 14, 2007, at 23:48 , Benjohn Barnes wrote: > > On 14 Mar 2007, at 19:57, Jason Roelofs wrote: > >> I haven't personally messed with this kind of stuff but code like >> this just >> makes me love Ruby even more. These types of, well DSL is really >> the best >> way to describe it, in such little code, makes Ruby such a blast >> to program >> in, and it's readable too! > > I think I must be getting too old, or I'm being a spring time > Scrouge... > > While it's neat, and it's cool Ruby can do that stuff, I've got to > ask "Why?". > > I've come across this used in DSLs, but I generally think, "I'm > sure you're going to get in to trouble down the line. Why don't you > just use the regular syntax?" > > I don't really see that it makes for an especially more concise > program, and really, it just seems to be introducing a different > syntax that's kind of crow bared in as an overloading of the > current syntax and semantics: as such, it doesn't seem to act in an > expected way. Frankly, it all seems reminiscent of some of the c++ > template techniques which, while terribly clever, don't generally > seem to actually achieve a lot that can't be done more simply in > other ways; and introduce so much complexity that even a seriously > good coder's complexity budget is nearly all used up with a very > small problem. > > No, you're right, I am getting old ;-) For code like this: subscribers.send_message(:chat, @current_user, chat_text) Instead of subscribers.each { |s| s.add_to_queue(:send_message, [:chat, @current_user, chat_text]) } It is also useful for transactions, where you can define a trampoline like this (writing this code in my mail program, it probably has bugs): def transaction queue = [] $exec = trampoline { |method, *args| @queue << [method, args] } yield queue.each do |method, args| __send__(method, *args) end end def exec $exec end Now you write code like this transaction do do_something exec.start_system1 do_something_else raise "Some error" if (something_failed) exec.start_system2 end If the transaction works, both start_system1 and start_system2 is called. Otherwise neither happens. It helps making the code straightforward, especially if the start_system calls are IO or similar that is difficult to reverse. /Christoffer