You misunderstand how r/fold works.
This is not quite true. There are two fundamental principles behind reducers. The first is that the process of reduction, stripped of all non-essentials, is "apply this function individually to every item in a collection, accumulating the result". Notice that there is no mention of order.
The second principle is, when reduction has been thus "reduced" to its essentials, it is possible for a *collection* to control how reductions are done over itself. Whether a reduction process has a particular order is a non-essential property that is provided or not-provided by the collection itself. The IReduceInit protocol is purposefully agnostic to order. Vectors implement it in an ordered way, but hash maps have no meaningful order.
So that's IReduceInit. The coll-fold protocol takes advantage of delegating the reduction implementation to the collection by allowing collections to provide a potentially-parallel reduction strategy. How this works is that the collection divides itself up into chunks, runs a normal reduction over each chunk using the same init value, then applies a "combine" function to combine the chunks. In the case of vectors, the chunks are combined in order, so the operation you are performing does not need to be commutative. However, the combine function still needs to be *associative*, because each individual sub-reduction is not initialized with the result of the previous reduction.
The problem here is misunderstanding the "combine" step of fold. You supply the same function apply-cmd for both reducing and combining. However, the reducing function is called with a set of "on" lights and a command, but the combine function is called with two sets of on lights (i.e., it is called with the result of two reductions). So in the combine phase, r/fold is calling apply-cmd something like this: (apply-cmd #{[1 1]} #{[2 2]}), which is not what it expects, hence your strange exception about Longs.
Anyway, the combine function must be associative, but this advent problem is *not* associative, because you cannot rearrange the order in which the toggle functions are run. Each toggle function must always have the final state of every previous line done. You could compute the commands *in between* the toggle commands in parallel (essentially coalescing them into a single "turn on" command), but you still need to run the whole sequence of toggle commands, from start to finish, in order.
Here is a simple example to illustrate:
; Our commands. :toggle simplified to illustrate the point.
(def cmds [[:on #{1 2}] [:toggle 2] [:on #{3}]])
;=> #'advent.a6/cmds
; Our reduction function, with initializing arity
(defn apply-cmd
([] #{})
([on [cmd arg]]
(case cmd
:on (into on arg)
:toggle (if (contains? on arg)
(disj on arg)
(conj on arg)))))
;=> #'advent.a6/apply-cmd
;; The correct answer, for reference
(r/reduce apply-cmd cmds)
;=> #{1 3}
Now let's perform the steps an r/fold would perform. We have three commands and will do two chunks, but we will divide the chunks differently. Here is what happens when we split between the second and third command:
; Chunk one
(r/reduce apply-cmd (subvec cmds 0 2))
;=> #{1}
; Chunk two
(r/reduce apply-cmd (subvec cmds 2))
;=> #{3}
; Combine
(into *1 *2)
;=> #{1 3}
; Looks ok...
Now lets try splitting between the first and second command:
; Chunk one
(r/reduce apply-cmd (subvec cmds 0 1))
;=> #{1 2}
; Chunk two
(r/reduce apply-cmd (subvec cmds 1))
;=> #{3 2}
;; Combine
(into *1 *2)
;=> #{1 3 2}
; WRONG ANSWER!!
Notice *how you split the commands up* affects the final answer, which means this algorithm can't be safely implemented with r/fold!