[prev in list] [next in list] [prev in thread] [next in thread]
List: ruby-talk
Subject: Re: Declarative relations between object attributes
From: Joel VanderWerf <joelvanderwerf () gmail ! com>
Date: 2010-09-13 0:19:53
Message-ID: 4C8D6E23.4080805 () gmail ! com
[Download RAW message or body]
On 09/12/2010 02:10 PM, Knut Franke wrote:
> Some time ago I stumbled over Cells[1], a Common Lisp extension allowing
> one
> to declare relations between instance variables (called slots in CL);
> i.e. a
> change to one variable will automatically recompute other variables
> depending
> on it. I think it's pretty neat, but using it in any interesting context
> is
> somewhat hampered by the fact that few people go through the
> considerable
> trouble involved in learning Common Lisp.
>
> Just today it occurred to me that it should be pretty easy to do
> something
> similar in Ruby. Indeed, a couple of codelines later, I had a Ruby
> version of
> the standard Cells example (well, a simplified version) running:
>
> class Motor
> cell :temperature, :status
> def initialize
> self.temperature = 0
> calculate :status do
> if self.temperature< 100
> :on
> else
> :off
> end
> end
> end
> end
> m = Motor.new
> m.observe(:temperature) {|old, new| puts "temperature: #{old} ->
> #{new}" }
> m.observe(:status) {|old, new| puts "status: #{old} -> #{new}" }
> m.temperature = 80
> m.temperature = 110
>
I wrote a library called observable for use in GUI MVC programming (with
FXRuby), something along those lines. One nice feature was pattern
matching on the changed value, so you could have separate handlers for
different ranges etc. Ruby's #=== methods are very cool and somewhat
underused. That might be a nice feature to add to your #observe method.
Here's the code:
http://redshift.sourceforge.net/observable/
Here's my version of your example:
require 'observable'
# Let's just include Observable globally. Conservatively, one would do:
#
# class C
# extend Observable
# include Observable::Match # if desired
# ...
# end
include Observable
include Observable::Match
class Motor
observable :temperature, :status
def initialize
self.temperature = 0
self.status = :on
when_temperature 0..100 do
self.status = :on
end
when_temperature 100..100000 do
self.status = :off
end
end
end
m = Motor.new
m.when_temperature CHANGES do |new, old|
puts "temperature: #{old} -> #{new}"
end
m.when_status CHANGES do |new, old|
puts "status: #{old} -> #{new}"
end
m.temperature = 80
m.temperature = 110
__END__
temperature: -> 0
status: -> on
temperature: 0 -> 80
temperature: 80 -> 110
status: on -> off
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic