defmodule Reactivity do alias Reactivity.Signal.Derived alias Reactivity.Signal.Generic alias Reactivity.Registry defmacro __using__(_options) do quote do import unquote(__MODULE__) alias Reactivity.Signal.Source alias Reactivity.Signal.Derived end end @doc """ Lift takes a regular function (a -> b) and lifts into a signal processing method. (signal a -> signal b). """ def lift(f) do lifted = fn(signal) -> # Create the intermediate node. deps = %{signal => 0} {:ok, ds} = Derived.new(f, nil, deps) Generic.add_child(signal, ds) {:ok, ds} end lifted end @doc """ Lift2 takes a function with two parameters (a -> b -> c) and lifts into a function that depends on two other signals (signal a -> signal b -> signal c). """ def lift2(f) do lifted = fn(signal1, signal2) -> # Create the intermediate node. deps = %{signal1 => 0, signal2 => 1} {:ok, ds} = Derived.new(f, nil, deps) Generic.add_child(signal1, ds) Generic.add_child(signal2, ds) {:ok, ds} end lifted end @doc """ Applies a lifted function on a signal, effectively subscribing to it. """ def apply(signal, f) do {:ok, new_signal} = f.(signal) new_signal end def apply2(signal1, signal2, f) do {:ok, new_signal} = f.(signal1, signal2) new_signal end @doc """ Convenience function to lift and immediatly apply a function to a signal. """ def liftapp(signal, f) do lifted = lift(f) Reactivity.apply(signal, lifted) end @doc """ Using a keyword to get a signal from the global environment. """ def source(name) do {:ok, signal} = Registry.get_source(name) signal end @doc""" Publishes a signal by registering it in the registry. """ def register(signal, name) do Registry.add_source(signal, name) signal end end