   elements are optional, additional values which parameterise the query
   performed.
 
-  `dynv` is an optional 3rd argument, `which is a vector of further input
+  `dynv` is an optional 3rd argument, which is a vector of further input
   signals (atoms, reactions, etc), NOT values. This argument exists for
   historical reasons and is borderline deprecated these days.
 



(defn reg-sub
  "For a given `query-id`, register a `computation` function and input `signals`.

  At an abstract level, a call to this function allows you to register 'the mechanism'
  to later fulfil a call to `(subscribe [query-id ...])`.

  To say that another way, reg-sub allows you to create a template for a node
  in the signal graph. But note: reg-sub does not cause a node to be created.
  It simply allows you to register the template from which such a
  node could be created, if it were needed, sometime later, when the call
  to `subscribe` is made.

  reg-sub needs three things:
    - a `query-id`
    - the required inputs for this node
    - a computation function for this node

  The `query-id` is always the 1st argument to reg-sub and it is typically
  a namespaced keyword.

  A computation function is always the last argument and it has this general form:
    `(input-signals, query-vector) -> a-value`.  The `query-vector` is the
    `query` passed to `(subscribe query)` (see there for details), which may contain
    additional arguments to further parametrise the query.

  What goes in between the 1st and last args can vary, but whatever is there will
  define the input signals part of the template, and, as a result, it will control
  what values the computation functions gets as a first argument.

  There's 3 ways this function can be called - 3 ways to supply input signals:

  1. No input signals given:

     (reg-sub
       :query-id
       a-computation-fn)   ;; (fn [db v]  ... a-value)

     The node's input signal defaults to `app-db`, and the value within `app-db` is
     is given as the 1st argument to the computation function.

  2. A signal function is supplied:

     (reg-sub
       :query-id
       signal-fn     ;; <-- here
       computation-fn)

     When a node is created from the template, the `signal-fn` will be called and it
     is expected to return the input signal(s) as either a singleton, if there is only
     one, or a sequence if there are many, or a map with the signals as the values.

     The values from the nominated signals will be supplied as the 1st argument to the
     computation function - either a singleton, sequence or map of them, paralleling
     the structure returned by the signal function.

     Here, is an example signal-fn, which returns a vector of input signals.

       (fn [query-vec dynamic-vec]
         [(subscribe [:a-sub])
          (subscribe [:b-sub])])

     For that signal function, the computation function must be written
     to expect a vector of values for its first argument.
       (fn [[a b] _] ....)

     If the signal function was simpler and returned a singleton, like this:
        (fn [query-vec dynamic-vec]
          (subscribe [:a-sub]))

     then the computation function must be written to expect a single value
     as the 1st argument:

        (fn [a _] ...)

  3. Syntax Sugar

     ```clj

       :a-b-sub
       :<- [:a-sub]
       :<- [:b-sub]
       (fn [[a b] [_]]    ;; 1st argument is a seq of two values
         {:a a :b b}))
     ```

     This 3rd variation is just syntactic sugar for the 2nd.  Instead of providing an
     `signals-fn` you provide one or more pairs of `:<-` and a subscription vector.

     If you supply only one pair a singleton will be supplied to the computation function, 
     as if you had supplied a `signal-fn` returning only a single value:

     ```clj
     (reg-sub
       :a-sub
       :<- [:a-sub]
       (fn [a _]      ;; only one pair, so 1st argument is a single value
         ...))
     ```

  For further understanding, read `/docs`, and look at the detailed comments in
