From: Stefan Rusterholz on
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
*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
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
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
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