[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Can I make a new function like attr_accessor?

Jack, Paul

12/15/2004 8:08:00 PM

I'm writing a program that has a bunch of components I'd like
to link together using Java-style property change events.

So I created a mixin module:

module Emitter

def addListener(listener)
@listeners.push(listener)
end

def removeLister(listener)
@listeners.delete(listener)
end

def emit(sym, oldValue)
@listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
end

end

In my component objects, I just make them include Emitter and invoke
"emit" on any mutator:

class ExampleComponent

include Emitter

def foo
@foo
end

def foo=(x)
old = @foo
@foo = x
emit(:foo, old)
end

end

I'd like to automate the creation of emitter properties, though. Just
like I can use attr_accessor to quickly create readable/writeable
attributes, I'd like a new attr_emitter function to quickly create
readable/writeable/emitable attributes.

But I can't figure out how to do that. :( Is it possible? It would
save me a LOT of redundant typing...

Thanks all,

-Paul



4 Answers

Its Me

12/15/2004 8:38:00 PM

0

It may be useful to look at this Ruby version of property change connectors
http://raa.ruby-lang.org/project/obse...


"Jack, Paul" <pjack@sfaf.org> wrote in message
news:F4F2EBDF8C16D5118B6500508BD32B4D02F8E1AA@earth.sfaf.org...
> I'm writing a program that has a bunch of components I'd like
> to link together using Java-style property change events.
>
> So I created a mixin module:
>
> module Emitter
>
> def addListener(listener)
> @listeners.push(listener)
> end
>
> def removeLister(listener)
> @listeners.delete(listener)
> end
>
> def emit(sym, oldValue)
> @listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
> end
>
> end
>
> In my component objects, I just make them include Emitter and invoke
> "emit" on any mutator:
>
> class ExampleComponent
>
> include Emitter
>
> def foo
> @foo
> end
>
> def foo=(x)
> old = @foo
> @foo = x
> emit(:foo, old)
> end
>
> end
>
> I'd like to automate the creation of emitter properties, though. Just
> like I can use attr_accessor to quickly create readable/writeable
> attributes, I'd like a new attr_emitter function to quickly create
> readable/writeable/emitable attributes.
>
> But I can't figure out how to do that. :( Is it possible? It would
> save me a LOT of redundant typing...
>
> Thanks all,
>
> -Paul


Thomas Counsell

12/15/2004 8:46:00 PM

0

Hi Paul

Not tested, but something like this should do the trick:

class Class
def attr_emitter( *syms )
syms.each do |sym|
class_eval( "def #{sym}; @#{sym} end" )
class_eval( "def #{sym}=(x)
old, @#{sym} = @#{sym}, x
emit(:#{sym}, old)
end" )
end
end
end

Note that I think you also need to define @listeners in your Emitter
module ..... (@listeners ||= [] ).push( listener) or some such.

Regards

Tom

On 15 Dec 2004, at 20:08, Jack, Paul wrote:

> I'm writing a program that has a bunch of components I'd like
> to link together using Java-style property change events.
>
> So I created a mixin module:
>
> module Emitter
>
> def addListener(listener)
> @listeners.push(listener)
> end
>
> def removeLister(listener)
> @listeners.delete(listener)
> end
>
> def emit(sym, oldValue)
> @listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
> end
>
> end
>
> In my component objects, I just make them include Emitter and invoke
> "emit" on any mutator:
>
> class ExampleComponent
>
> include Emitter
>
> def foo
> @foo
> end
>
> def foo=(x)
> old = @foo
> @foo = x
> emit(:foo, old)
> end
>
> end
>
> I'd like to automate the creation of emitter properties, though. Just
> like I can use attr_accessor to quickly create readable/writeable
> attributes, I'd like a new attr_emitter function to quickly create
> readable/writeable/emitable attributes.
>
> But I can't figure out how to do that. :( Is it possible? It would
> save me a LOT of redundant typing...
>
> Thanks all,
>
> -Paul
>
>



Francis Hwang

12/15/2004 8:47:00 PM

0


On Dec 16, 2004, at 4:08 AM, Jack, Paul wrote:
> I'd like to automate the creation of emitter properties, though. Just
> like I can use attr_accessor to quickly create readable/writeable
> attributes, I'd like a new attr_emitter function to quickly create
> readable/writeable/emitable attributes.
>
> But I can't figure out how to do that. :( Is it possible? It would
> save me a LOT of redundant typing...

It's quite possible, and a very useful way to add domain-specific
syntactic sugar. Basically you define it as a module-level or
class-level method.

module Emitter
def self.attr_emitter( args )
...
end
end

Remember that in Ruby there's no distinction between compile-time and
runtime. So when you define a class like this:

class ExampleComponent
include Emitter
attr_emitter arg1, arg2
end

The call to "attr_emitter" isn't actually a special compile-time flag;
it's a module- or class-level method that you're calling at runtime, as
you define the class.

BTW, if you're just coming from Ruby to Java, I wrote an article on my
blog that you might find really useful: http://f...bl...

Francis Hwang
http://f...



Robert Klemme

12/16/2004 8:48:00 AM

0


"Thomas Counsell" <tamc2@cam.ac.uk> schrieb im Newsbeitrag
news:4BEB5F89-4EDA-11D9-B9F5-000393CC0FA0@cam.ac.uk...
> Hi Paul
>
> Not tested, but something like this should do the trick:
>
> class Class
> def attr_emitter( *syms )
> syms.each do |sym|
> class_eval( "def #{sym}; @#{sym} end" )
> class_eval( "def #{sym}=(x)
> old, @#{sym} = @#{sym}, x
> emit(:#{sym}, old)
> end" )
> end
> end
> end

Preferrable put that code into class Module. That way even modules can
use attr_emitter.

> Note that I think you also need to define @listeners in your Emitter
> module ..... (@listeners ||= [] ).push( listener) or some such.

Yeah. Also you can automate inclusion of the module. So this would be my
implementation:

module Emitter
def listeners; @listeners ||= [] end

def addListener(listener)
listeners.push(listener)
end

def removeLister(listener)
listeners.delete(listener)
end

def emit(sym, oldValue)
listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
end
end

class Module
def attr_emitter(*syms)
syms.each do |sym|
class_eval( "def #{sym}; @#{sym} end; def #{sym}=(x) old, @#{sym} =
@#{sym}, x ; emit(:#{sym}, old) end" )
end

include Emitter
end
end

Kind regards

robert