           (fn [table-request]
             (reduce into []
              (for [action (keys table-request)
-                   :let [items (multi-kvs (table-request action))]]
+                   :let [items (attr-multi-vs (table-request action))]]
                (mapv (partial write-request action) items))))
           requests))))))
 


;;;; API - batch ops

(defn- multi-kvs
  "[{<k1> <v1s*> ...} ...]* -> [{k1 v1 ...} ...] (* => optional vec)"
  [kvs]
  (let [ensure-coll (fn [x] (if (coll?* x) x [x]))]
    (reduce (fn [r kvs]
              (let [ks (keys kvs)
                    vs (mapv ensure-coll (vals kvs))]
                (when (> (count (filter next vs)) 1)
                  (-> (Exception. "Can range over only a single attr's values")
                      (throw)))
                (into r (mapv (comp clj-item->db-item (partial zipmap ks))
                              (apply utils/cartesian-product vs)))))
            [] (ensure-coll kvs))))

(comment (multi-kvs {:a "a1" :b ["b1" "b2" "b3"] :c ["c1" "c2"]})
         (multi-kvs {:a "a1" :b ["b1" "b2" "b3"] :c ["c1"]}))

(defn- batch-request-items
  "{<table> <request> ...} -> {<table> KeysAndAttributes> ...}"

     (doto-maybe (KeysAndAttributes.) g
       attrs       (.setAttributesToGet (mapv name g))
       consistent? (.setConsistentRead  g)
       :always     (.setKeys (attr-multi-vs prim-kvs))))
   requests))

(comment (batch-request-items {:my-table {:prim-kvs [{:my-hash  ["a" "b"]
