From: Stefan Rusterholz on 18 Aug 2007 17:57 ashishwave wrote: > ruby integrates power of functional programming from lisp , purest OO > from smalltalk, prototype oriented power from self etc etc into one > single language > > i just was wondering that whether the heavy developers/users of > reactive languages like kanaputs or reactive-C etc will ever get > reactive features in ruby. > > in kanaputs, If the variable 'c' is defined as c = a + b; and if the > reactivity of 'c' is set (c.reactive = true;), then each time the > value of 'a' or 'b' changes then the value of 'c' is updated as the > result of the addition > > > bye :-) > Ashish > ashishwave(a)yahoo.com. Not the same, probably rather slow, but hey: class Expression < BlankSlate def initialize(&expression) @expression = expression end def method_missing(*a, &b) @expression.call.send(*a, &b) end end a = 1 b = 2 c = Expression.new { a + b } c + 3 # => 6 a = 5 c + 3 # => 10 Have fun ;-) Regards Stefan -- Posted via http://www.ruby-forum.com/.
From: benjohn on 20 Aug 2007 06:24 *snip* > I've always been a partisan of loosely-coupled systems that use > idempotent > messaging. I'm still hopeful that such a thing will come to Ruby. (This > in > fact was precisely the reason that the EventMachine library was > developed, > and it's still on the roadmap.) *snip* If you've got some links you could share about idempotent messaging, I'd like to read them. The hits I'm getting seem to be about interprocess protocol, rather than an approach that you'd also use intraprocess.
From: Martin DeMello on 20 Aug 2007 06:35 On 8/17/07, ashishwave <ashishwave(a)gmail.com> wrote: > ruby integrates power of functional programming from lisp , purest OO > from smalltalk, prototype oriented power from self etc etc into one > single language > > i just was wondering that whether the heavy developers/users of > reactive languages like kanaputs or reactive-C etc will ever get > reactive features in ruby. > > in kanaputs, If the variable 'c' is defined as c = a + b; and if the > reactivity of 'c' is set (c.reactive = true;), then each time the > value of 'a' or 'b' changes then the value of 'c' is updated as the > result of the addition http://common-lisp.net/project/cells/ is an interesting common lisp project in that area martin
From: Brad Phelan on 20 Aug 2007 07:40 ashishwave wrote: > ruby integrates power of functional programming from lisp , purest OO > from smalltalk, prototype oriented power from self etc etc into one > single language > > i just was wondering that whether the heavy developers/users of > reactive languages like kanaputs or reactive-C etc will ever get > reactive features in ruby. > > in kanaputs, If the variable 'c' is defined as c = a + b; and if the > reactivity of 'c' is set (c.reactive = true;), then each time the > value of 'a' or 'b' changes then the value of 'c' is updated as the > result of the addition > > > bye :-) > Ashish > ashishwave(a)yahoo.com. > I think this may give you some ideas. A Reactive object has a number of reactive objects it depends on as well as a block to calculate it's own value. The self value is calculated lazily and cached. It is only recalculated when an object it depends on set's it's dirty flag by calling notify. class Reactive # On change of value dependants are notified # of updates def value=(val) @value=val @depends.each do |d| d.notify end end # Add d as a listener def notify_me d @depends << d end # Get the cached value unless the # dirty flag has been set then # recalc the value from the block def value if @block && @dirty argv = [] @args.each do |a| if a.respond_to? :value argv << a.value else argv << a end end @value = @block.call *argv end @dirty=false @value end # Notify this object that at # least one dependant has changed. def notify @dirty=true end # Init the class with the dependant # reative variables and a block to # evaluate to compute the value # of this object. def initialize *args, &block @depends = [] if block_given? @args = args @block = block @args.each do |a| a.notify_me self end else # This is a literal @value = *args end @dirty=true end end a = Reactive.new(10) b = Reactive.new(20) c = Reactive.new a,b do |_a,_b| _a + _b end d = Reactive.new b,c do |_b,_c| _b + _c end vars = {:a=>a,:b=>b,:c=>c,:d=>d} vars.each do |k,v| puts "#{k} #{v.value}" end puts "------------------" a.value = 40 vars.each do |k,v| puts "#{k} #{v.value}" end ------------------ Output is :!ruby reactive.rb c 30 d 50 a 10 b 20 ------------------ c 60 d 50 a 40 b 20 -- Brad Phelan http://xtargets.com
From: Christian Neukirchen on 8 Sep 2007 11:56
ashishwave <ashishwave(a)gmail.com> writes: > ruby integrates power of functional programming from lisp , purest OO > from smalltalk, prototype oriented power from self etc etc into one > single language > > i just was wondering that whether the heavy developers/users of > reactive languages like kanaputs or reactive-C etc will ever get > reactive features in ruby. > > in kanaputs, If the variable 'c' is defined as c = a + b; and if the > reactivity of 'c' is set (c.reactive = true;), then each time the > value of 'a' or 'b' changes then the value of 'c' is updated as the > result of the addition > > > bye :-) > Ashish > ashishwave(a)yahoo.com. Half-way done ideas wrt that, inspired by flapjax. No warranty. $ cat /Users/chris/mess//2006/49/frp.rb require '/Users/chris/projects/blogcode/dynamic.rb' Thread.abort_on_exception = true Dynamic.variable :current_calc class Var def initialize(value=nil) @affects = [] @value = value end def set!(v) @value = v propagate v end def ~ @affects << Dynamic.current_calc if Dynamic.current_calc @value end def propagate @affects.each { |a| a.call } end def map(init=nil, &block) new = Var.new init Calc.new { new.set! block.call(~self) } new end def inject(initial, &block) a = initial map { |e| a = block.call a, e } end def constant(const) map { const } end def hold(initial, &block) map(initial) { block.call } end def filter(&block) new = Var.new Calc.new { this = ~self if block.call this new.set! this end } new end def merge(other) new = Var.new Calc.new { new.set! ~self } Calc.new { new.set! ~other } new end def calm(window, &block) last = Time.now merge(Timer.for(window)).filter { p [:calm, last, Time.now] r = (Time.now - last) > window last = Time.now r } end end class Calc < Proc attr_reader :timers def initialize(&block) @timers = {} super(&block) Dynamic.let :current_calc => self do call end end end class Timer attr_reader :var def self.for(period) if Dynamic.current_calc.nil? new(period).var else Dynamic.current_calc.timers.fetch(period) { Dynamic.current_calc.timers[period] = new(period) }.var end end def initialize(period) @period = period @var = Var.new Time.now.to_f Thread.new { loop { p "sleeping for #@period" sleep @period @var.set! Time.now.to_f } } end end x = Var.new 5 # Calc.new { p ["at time ", ~Timer.for(0.1), "x is ", ~x] } Calc.new { p ["x is ", ~x] } y = x.map { |z| z * 2 } Calc.new { p ["y is now", ~y] } sum = x.inject(0) { |a,e| a + e } Calc.new { p ["sum is now", ~sum] } Timer.for(5).map { p "tick!" } x.calm(2).map(false) { |v| p "no input for 2 secs!" } # Timer.for(10).merge(x).map { p "either 10s or x" } x.set! 7 while line = gets.to_i x.set! line p ["set to ", ~x] end -- Christian Neukirchen <chneukirchen(a)gmail.com> http://chneukirchen.org |