If I reduce a next.jdbc plan without providing an init val (`(reduce f (next.jdbc/plan ...))`), I get this error: class next.jdbc.result_set$eval26051$fn$reify__26053 cannot be cast to class clojure.lang.IReduce
Passing in nil for the init val makes it work as expected.
Is that how it is supposed to work?
Yes. There is no sensible default so that form of reduce is not supported on plan. Pretty sure the docs explicitly call that out (but I'm on my phone right now).
doc doesnβt mention it
> Returns a reducible that
but source clearly indicates it
(^clojure.lang.IReduceInit
[stmt]
(p/-execute stmt [] {}))
In Getting Started, it says plan returns an IReduceInit but that's probably not quite clear enough. I'll update the docs and the docstring.
Ok I see. Yea I checked what the clojure interfaces for reduce were after writing this, but wouldn't have known that that meant only the init val arity was supported.
For a sensible default, would [] be wrong? (Since a result set is like a collection / seq)
if you intend to accumulate rows, yes. if you intend to sum something, no. If you intend to get stats in a map, no. etc.
Right but that isn't the default thing you get from a result set, so it makes sense that you would override the default in such cases
I think nil might be another value that some people would reasonably expect to be the default though, so the fact that there are 2 sensible values might be reason enough for the existing logic.
@dpsutton isn't that an argument against IReduce in principle though?
yes it is π
but here fits that general argument i think
Rich has said that the non-init form of reduce was a mistake.
Ah, fair enough
nil as a default would accumulate rows in reverse order. a transient is probably a good call here as well but requires the reducing function to play along. far better to just own the initial value
I see the benefits and generally do that. The downside is the surprise - not working like reduce normally.
reduce without an init is really weird
> If val is not supplied, > returns the result of applying f to the first 2 items in coll, then > applying f to that result and the 3rd item, etc. If coll contains no > items, f must accept no arguments as well, and reduce returns the > result of calling f with no arguments. If coll has only 1 item, it > is returned and f is not called. If val is supplied, returns the > result of applying f to val and the first item in coll, then > applying f to that result and the 2nd item, etc. If coll contains no > items, returns val and f is not called. the docstring of reduce is convoluted to talk about the lack of an init. and is quite surprising
Hmm yea you're right, that is very strange
OK, docs and docstrings are updated for the next release.