Events in Ruby

Napoleon

Veteran
Veteran
Joined
Dec 29, 2012
Messages
869
Reaction score
97
First Language
Dutch
Primarily Uses
EDIT/UPDATE: I created 2 scripts for it now: http://napprod.wordpress.com/2013/07/24/event/ & http://napprod.wordpress.com/2013/07/24/event-hook/

I tried to implement events in Ruby.

My event base class

class Event    def initialize    @listeners = []  end   def +(*methods)    methods.each { |method|      @listeners << method if !@listeners.include?(method)    }  end   def -(*methods)    methods.each { |method|      @listeners.reject!{|m| m == method}    }  end   def clear    @listeners = []  end   def start(*params)    @listeners.each{|m| m.call(*params)}  end   def to_s    return "obj id: '#{self.object_id}' methods: #{@listeners}"  endend
Testing it:

module Debug  class Foo1    attr_accessor :on_foo        def initialize      @on_foo = Event.new()    end        def foo      p 'foo1'      @on_foo.start    end  end   class Foo2    def initialize      # do nothing    end        def foo      p 'foo2'    end  end   class Foo3    def initialize      # do nothing    end        def foo      p 'foo3'    end  end      def self.test1    a = Foo1.new()    b = Foo2.new()    c = Foo3.new()        a.on_foo + b.method:)foo)    a.on_foo + b.method:)foo)    a.on_foo + c.method:)foo)#~    a.on_foo + b.method:)foo), c.method:)foo)    a.foo              #if you see printed:    #"foo1"    #"foo2"    #"foo3"    # then it works.        p '-----'    a.on_foo - b.method:)foo)    a.foo    #if you see printed:    #"foo1"    #"foo3"    # then it works.      end   self.test1end
Replacing the = to a += in a.on_foo + b.foo crashes.

Also "a.on_foo + b.method:)foo)" is not really 'friendly' to code. I just want:

a.on_foo += b.fooa.on_foo -= b.foo"a.on_foo + b.method:)foo), c.method:)foo)" also crashes. But the + is implemented so it accepts multiple parameters.
 
Last edited by a moderator:

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
a.on_foo + b.method:)foo), c.method:)foo)

I'm not sure if that kind of syntax actually works. The error message isn't giving you a method call error.
 

Napoleon

Veteran
Veteran
Joined
Dec 29, 2012
Messages
869
Reaction score
97
First Language
Dutch
Primarily Uses
a.on_foo.+ b.method:)foo), c.method:)foo)That works. But adding a dot is kinda... silly on an operator. I replaced it with the << operator but that one has the same problem.

Also I want to say:

attr_accessor :on_foo, Event.new() # initialize it right away.But it only works in Ruby on Rails. Not in RM's Ruby.
 

Galenmereth

Retired
Veteran
Joined
May 15, 2013
Messages
2,248
Reaction score
2,158
First Language
English
Primarily Uses
N/A
That's because Rails is a framework built on Ruby; there's a lot of functionality in Rails which is not standard in the Ruby language. If you want to read documentation on the Ruby language itself, I'd recommend checking out http://ruby-doc.org/
 

Solistra

Veteran
Veteran
Joined
Aug 15, 2012
Messages
593
Reaction score
247
Primarily Uses
The error that you're getting is a syntax error. Essentially, the Ruby interpreter isn't sure of how to execute the code that you're giving it due to its ambiguous nature. Using the dot syntax explicitly makes it possible for the interpreter to sort through that ambiguity and figure out exactly what it is you're trying to do (from the eyes of the interpreter, at least).


Honestly, Ruby's love of syntactical sugar restricts what you can do with methods such as '+'. The a + b form of using the '+' method is really just syntactical sugar for sending the '+' method to the receiver with 'b' as its parameter. At the same time, the 'this', 'is', 'an', 'array' form of creating arrays is also syntactical sugar (obviously). As such, trying to do a + b, c, d is confusing to the interpreter -- it can't tell what you're trying to do with that code. From the interpreter's standpoint, it can't be sure of where that array begins and ends due to Ruby's way of interpreting whitespace.


With that in mind, why not make your methods explicit? Use an 'add' and 'remove' method and just use it like you would any other method. It's simple, unambiguous, and not problematic for the interpreter.


On that note, I'd also like to add that I don't really like the fact that you're using 'methods' as a parameter -- everything which is a descendent of Object already has a method entitled 'methods', which isn't really a problem (the interpreter takes care of that confusion by accessing the array before the method), but is still very ambiguous and potentially confusing. Just something to think about.
 

Napoleon

Veteran
Veteran
Joined
Dec 29, 2012
Messages
869
Reaction score
97
First Language
Dutch
Primarily Uses
Ohyeah that's true.

So I tried creating it myself using meta programming:

class Class  def attr_accessor_init(attr_name, init_value)    attr_name = attr_name.to_s        class_eval %Q{      def #{attr_name}        @#{attr_name}      end      def #{attr_name}=(value)        @#{attr_name} = value      end            $class_init ||= {}      $class_init[self.object_id] ||= {}      $class_init[self.object_id][attr_name] = #{init_value}    }  end # attr_accessor_init   def new(*args, &blk)        o = allocate        o.send:)initialize, *args, &blk)                if $class_init && $class_init.has_key?(self.object_id)          $class_init[self.object_id].each {|k, v|            eval("o.#{k} = #{v}")          }          $class_init.delete(self.object_id)        end                o          end # def newend # Classclass Test123  attr_accessor_init :aa, 4.5 # << works  attr_accessor_init :bb, 5.5002 # << works  attr_accessor_init :c, 'g' # <<<<<<<<<<<<<<<<< crash? Undefined local variable or method 'g' for Test123   def initialize      endendtemp = Test123.newp temp.aap temp.bbp temp.cIt also crashes for symbols and for other classes. Only fixnums/floats seem to work. Strange.

EDIT: You made that post while I was writing this one.

On that note, I'd also like to add that I don't really like the fact that you're using 'methods' as a parameter -- everything which is a descendent of Object already has a method entitled 'methods', which isn't really a problem (the interpreter takes care of that confusion by accessing the array before the method), but is still very ambiguous and potentially confusing. Just something to think about.
Oh I didn't know that. I will change the parameter name then.

And yes I should make them explicit I guess.
 
Last edited by a moderator:

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
I think we should choose a different word instead of "event" as event is already reserved for RM's notion of events and it would get confusing. While event is the generally accepted word, we can probably make something up in the context of RM lol


RM's event object is sort of similar in the sense that they are the event handlers that are fired whenever we trigger them somehow...but even then, if it becomes widely used then new users are going to get pretty confused.
 
Last edited by a moderator:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,865
Messages
1,017,059
Members
137,574
Latest member
nikisknight
Top