        :a-b-sub
        :<- [:a-sub]
        :<- [:b-sub]
-       (fn [[a b] [_]] {:a a :b b}))
+       (fn [[a b] [_]]    ;; 1st argument is a seq of two values
+         {:a a :b b}))
      ```
 
-     This 3rd variation is syntactic sugar for the 2nd.  Instead of providing an
-     `input signals` function, other subscriptions are used as automatic `input
-     signals`: Each pair of `:<-` and a subscription vector is equivalent to a call to
-     `(subscribe [:a-sub])`.
-
-     Beware that in this syntax a single `:<-` pair is *not* wrapped in a vector, hence
-     the same rule as for the 2nd variation applies: If you only provide one `input
-     signal`, the computation function must expect a single value as the 1st argument:
+     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 _] ...))
+       (fn [a _]      ;; only one pair, so 1st argument is a single value
+         ...))
      ```
 
   For further understanding, read `/docs`, and look at the detailed comments in

  elements are optional, additional values which parameterise the query
  performed.

  `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 two functions: a `computation` function and an `input signals` function.
  
  During program execution, a call to `subscribe`, such as `(subscribe [:sub-id 3 "blue"])`,
  will create a new `:sub-id` node in the Signal Graph. And, at that time, re-frame
  needs to know how to create the node.   By calling `reg-sub`, you are registering 
  "the template" or "the mechanism" by which nodes in the Signal Graph can be created. 

  Repeating: calling `reg-sub` does not create a node. It only creates the template
  from which nodes can be created later. 
  
  `reg-sub` arguments are:  
    - a `query-id` (typically a namespaced keyword)
    - a function which returns the inputs required by this kind of node (3 variations of this)
    - a function which computes the value of this kind of node 

  The`computation function` is always the last argument supplied and it is expected to have the signature: 
    `(input-values, query-vector) -> a-value`
  
  When this computation function is called, `query-vector` will be what was passed as the first 
  argument the `subscribe` causing the node to be created. So if the call was `(subscribe [:sub-id 3 "blue"])` 
  then the `query-vector` supplied to the computaton function will be `[:sub-id 3 "blue"]`.

  The arguments supplied between the `query-id` and the `computation-function` can vary in 3 ways, 
  but whatever is there will define the `input signals` part of the template, and this controls
  what `input-values` the `computation function` gets when it is called. 

  `reg-sub` can be called in 3 ways, because there are 3 ways to supply input signals:

  1. No input signals given:
      ```clj
     (reg-sub
       :query-id
       a-computation-fn)   ;; (fn [db v]  ... a-value)
     ```

     In the absence of an `input-fn`, the node's input signal defaults to `app-db`
     and, as a result, the value within `app-db` (a map) is
     is given as the 1st argument when `a-computation-fn` is called.

  2. A signal function is explicitly supplied:
     ```clj
     (reg-sub
       :query-id
       signal-fn     ;; <-- here
       computation-fn)
     ```
     
     This is the most canonical and instructive of the three variations.
     
     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 returned nominated signals will be supplied as the 1st argument to  
     the `a-computation-fn` when it is called - and subject to what this `signal-fn` returns, 
     this value will be either a singleton, sequence or map of them (paralleling
     the structure returned by the `signal-fn`).

     This example `signal-fn` returns a vector of input signals.
       ```clj
       (fn [query-vec dynamic-vec]
         [(subscribe [:a-sub])
          (subscribe [:b-sub])])
       ```
     The associated computation function must be written
     to expect a vector of values for its first argument:
       ```clj
       (fn [[a b] _]     ;; 1st argument is a seq of two values
         ....)
        ```

     If, on the other hand, the signal function was simpler and returned a singleton, like this:
        ```clj
        (fn [query-vec dynamic-vec]
          (subscribe [:a-sub]))
        ```
     then the associated computation function must be written to expect a single value
     as the 1st argument:
        ```clj
        (fn [a _]       ;; 1st argument is a single value
          ...)
        ```
  3. Syntax Sugar

     ```clj
