ashishwave [email protected] writes:

value of ‘a’ or ‘b’ changes then the value of ‘c’ is updated as the

result of the addition

bye

Ashish

[email protected]

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