refactor propagator to remove remaining references to cell
now expects inputs and outputs to be lambdas that call cell/content and cell/add-content! respectively
This commit is contained in:
parent
35e86859e8
commit
369fd89e62
1 changed files with 40 additions and 32 deletions
|
@ -1,45 +1,53 @@
|
||||||
(ns prop-net.propagator
|
(ns prop-net.propagator)
|
||||||
(:require [prop-net.cell :as c]))
|
|
||||||
|
(def ^:private no-output [])
|
||||||
|
(defn- no-output? [output]
|
||||||
|
(= output no-output))
|
||||||
|
|
||||||
|
|
||||||
(defprotocol IPropagator
|
(defprotocol IPropagator
|
||||||
(inputs [this])
|
(inputs
|
||||||
(output [this])
|
[this]
|
||||||
(add-input! [this input-cell])
|
"returns the functions to be called to retrieve the propagators inputs")
|
||||||
(add-output! [this output-cell])
|
(output
|
||||||
(apply! [this]))
|
[this]
|
||||||
|
"returns the function to be called to set the result content of output cell")
|
||||||
|
(add-input!
|
||||||
|
[this input-lookup]
|
||||||
|
"add an input function to retrieve the content of a cell")
|
||||||
|
(add-output!
|
||||||
|
[this output-set!]
|
||||||
|
"add an output function to set the content of a cell")
|
||||||
|
(apply!
|
||||||
|
[this]
|
||||||
|
"applies the propagator function to results of all input-lookup
|
||||||
|
calls and calls the output function with the result"))
|
||||||
|
|
||||||
(defrecord Propagator
|
(defrecord Propagator
|
||||||
[inputs output function]
|
[input-getters output-setter function]
|
||||||
IPropagator
|
IPropagator
|
||||||
(inputs [this] (deref (:inputs this)))
|
(inputs [this] (deref (:input-getters this)))
|
||||||
(output [this] (deref (:output this)))
|
(output [this] (deref (:output-setter this)))
|
||||||
(add-input! [this input-cell]
|
(add-input! [this input-func]
|
||||||
;; this is some java shenanigans prop_net.cell.Cell
|
(do (swap! (:input-getters this) conj input-func)
|
||||||
(when (not (instance? prop_net.cell.Cell input-cell))
|
:ok))
|
||||||
(throw (ex-info "Input must be a cell" {:input input-cell})))
|
(add-output! [this output-set!]
|
||||||
(let [old-inputs (deref (:inputs this))]
|
(if (no-output? (output this))
|
||||||
(do (swap! (:inputs this) conj input-cell)
|
(do (reset! (:output-setter this) output-set!)
|
||||||
:ok)))
|
|
||||||
(add-output! [this output-cell]
|
|
||||||
;; TODO for some reason instance? is not evaluating to true here, but types should really be checked
|
|
||||||
;; from the net itself
|
|
||||||
;; (when (not (instance? prop_net.cell.Cell output-cell))
|
|
||||||
;; (throw (ex-info "Output must be a cell" {:output output-cell
|
|
||||||
;; :type (type output-cell)})))
|
|
||||||
(if (c/nothing? (deref (:output this)))
|
|
||||||
(do (reset! (:output this) output-cell)
|
|
||||||
:ok)
|
:ok)
|
||||||
(throw (ex-info "Output already set" {:propagator this :conflict output}))))
|
(throw (ex-info "Output cell already present" {:propagator this :conflict output}))))
|
||||||
|
;; apply will call output with the result of calling :function with all inputs
|
||||||
(apply! [this]
|
(apply! [this]
|
||||||
(let [input-cells (deref (:inputs this))
|
(let [input-getters (vec (inputs this))
|
||||||
output-cell (deref (:outputs this))]
|
output-set! (output this)]
|
||||||
(c/add-content! output-cell (apply (:function this)
|
(output-set! (apply (:function this)
|
||||||
(map c/content input-cells))))))
|
;; there might be a cleaner way to apply each lookup?
|
||||||
|
(map (fn [lookup] (lookup))
|
||||||
|
input-getters))))))
|
||||||
|
|
||||||
(defn function->propagator
|
(defn function->propagator
|
||||||
[func]
|
[func]
|
||||||
(map->Propagator
|
(map->Propagator
|
||||||
{:inputs (atom #{})
|
{:input-getters (atom #{})
|
||||||
:output (atom c/nothing)
|
:output-setter (atom no-output)
|
||||||
:function func}))
|
:function func}))
|
||||||
|
|
Loading…
Reference in a new issue