Based off of functional reactive programming, oscillo gives you a signal that represents a value changing over time. You can manipulate signals and combine them together in various ways.
- source: https://github.com/evant/oscillo
- documentation: http://rubydoc.info/github/evant/oscillo/frames
Add this line to your application's Gemfile:
gem 'oscillo'
And then execute:
$ bundle
Or install it yourself as:
$ gem install oscillo
Creating a signal is as simple as
s = Oscillo::Signal.new
You modify the value of the signal with s << :value
and you get the current
value of the signal with s.value
, or s.val
if you want to save a couple of
letters.
If you want to give a signal a starting value, you just pass it to the constructor.
s = Oscillo::Signal.new(0)
If you pass another signal as an argument to new
, the signal's value will
follow the other one.
a = Oscillo::Signal.new
b = Oscillo::Signal.new(a)
a << :value
b.val #=> :value
You can pass a block to new
to modify how the new signal follows the old.
a = Oscillo::Signal.new(0)
b = Oscillo::Signal.new(a) { |v| v * 2 }
a << 3
b.val #=> 6
You can also follow multiple signals at once. The new signal will change if any of the signal that you follow changes.
a = Oscillo::Signal.new(0)
b = Oscillo::Signal.new(0)
c = Oscillo::Signal.new(a, b) { |v1, v2| v1 + v2 }
a << 2
c.val #=> 2
b << 3
c.val #=> 5
Eventually, you want to perform some action when the value of the signal
changes. To do this, register a callback with the #on_change
method. You can
also use #each
if you want to think of it as an Enumerable.
s = Oscillo::Signal.new
s.on_change { |v| puts "The new value is: #{v}" }
s << 1
#=> "The new value is: 1
The last argument given to the block passed to new is the signal itself. This is so you utilize other methods to query the signal and modify it's changed value.
{Oscillo::Signal#abort} aborts the new value change, keeping the old one.
a = Oscillo::Signal.new
b = Oscillo::Signal.new(a) { |v, s| s.abort if v == :bad; v }
a << :good
b.val #=> :good
a << :bad
b.val #=> :bad
{Oscillo::Signal#source} gives the original signal that caused the cascade of changes. This is useful if you are following multiple signals and want to know which one actually changed.
a = Oscillo::Signal.new
b = Oscillo::Signal.new
c = Oscillo::Signal.new(a, b) do |v1, v2, s|
"The last change was to #{s.source.val}"
end
a << 1
c.val #=> "The last change was to 1"
b << 2
c.val #=> "The last change was to 2"
You can combine signals together in different ways. For example, {Oscillo::Combine.either} updates the new signal to the value of whichever was the last signal to change.
a = Oscillo::Signal.new
b = Oscillo::Signal.new
c = Oscillo::Combine.either(a, b)
a << "a changed"
c.val #=> "a changed"
b << "b changed"
c.val #=> "b changed"
See {Oscillo::Combine} for all combination methods.
A signal can thought of a sequence of values over time. Therefore, {Oscillo::Signal} implements a large number of Enumerable's methods. For example,
a = Oscillo::Signal.new(0)
b = a.map { |v| v ** 2 }
a << 3
b.val #=> 9
See {Oscillo::Enumerable} for all the methods implemented.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request