cgrand / xforms

Extra transducers and reducing fns for Clojure(script)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why is there no first?

Bost opened this issue · comments

commented

I wonder what's the reason behind not having:

(defn first
  "Reducing function that returns the first value."
  ([] nil)
  ([x] x)
  ([x _] x))

? as a "complement" of last.

Edit:
Huh, interestingly enough it won't work at all:

(defn dbg-first
  ([] nil)
  ([x] x)
  ([x y]
   (println ";; x" x "y" y)
   x))

(transduce (comp
            (filter odd?)
            (map inc))
           dbg-first [42]
           [1 2 3 4])
;; x [42] y 2
;; x [42] y 4
;; => [42]

I'm getting convinced this issue can be closed. Happy Xmas! :)

You are lookings for rfs/some:

(defn some
  "Reducing function that returns the first logical true value."
  ([] nil)
  ([x] x)
  ([_ x] (when x (reduced x))))
commented

Thanks for pointing out the rfs/some. However there's something about it:

(require
 '[net.cgrand.xforms :as x]
 '[net.cgrand.xforms.rfs :as rfs])

(into {} (x/by-key identity rfs/last) [1 2 3 4]) ;; => {1 1, 2 2, 3 3, 4 4}
(into {} (x/by-key identity x/last) [1 2 3 4])    ;; => {1 1, 2 2, 3 3, 4 4}
(into {} (x/by-key identity rfs/some) [1 2 3 4]) ;; => {1 1, 2 2, 3 3, 4 4}
;; (into {} (x/by-key identity x/some) [1 2 3 4]) ;; throws 'Wrong number of args (1) passed to: net.cgrand.xforms/some'

Also:

(reduce rfs/last [1 2 3 4]) ;; => 4
(reduce rfs/some [1 2 3 4]) ;; => returns 2; I'd expect 1
(x/some identity [1 2 3 4]) ;; => 1
(x/last identity [1 2 3 4]) ;; throws 'Wrong number of args (2) passed to: net.cgrand.xforms/reduce/fn--35656'

And here I'd expect same types:

(type (rfs/last identity [1 2 3 4])) ;; => clojure.lang.PersistentVector
(type (rfs/some identity [1 2 3 4])) ;; => clojure.lang.Reduced
(reduce rfs/some [1 2 3 4]) ;; => returns 2; I'd expect 1

rtfs/* are meant to be used with transduce not reduce (whose no-init arity semantics are not great imo):

(transduce identity rfs/some [1 2 3 4]) ;; => returns 1

x/last is a transducer not a transducing context. However x/some is a transducing context

=> (into [] x/last [1 2 3 4])
[4]
=> (x/some x/last [1 2 3 4])
4