Fork me on GitHub
#beginners
<
2015-09-03
>
roberto02:09:05

is there a clojure core function that finds elements inside an array? Something like (find-in coll pred)

roberto02:09:39

I implemented my own, but I feel as if there is something in core that I am overlooking:

(defn find-in
  "Finds an item in a collection.
  It returns the first item whose pred returns true.
  The predicate function receives the current item in the iteration."
  [pred coll]
  (reduce (fn [acc x]
            (if (empty? acc)
              (if (apply pred x)
                x
                acc)
              acc))
          {}
          coll))

roberto02:09:54

i only want the first result

potetm02:09:32

(first (filter ...))?

teamaverage02:09:36

(comp (first (filter))

potetm02:09:00

some occasionally fits the bill.

roberto02:09:04

(comp first filter) worked

roberto02:09:30

I think this can be more efficient if I use recursion, that way it exists as soon as it finds a result

potetm02:09:37

I would assume so as well.

teamaverage02:09:00

Yeah instead of building up a list

teamaverage02:09:08

You could use a loop

teamaverage02:09:23

I guess when you find your value you break instead of calling recur

roberto02:09:16

my solution:

(def my-list [{:name "A" :items [1 2 3]} {:name "B" :items [4 5 6]}])

(defn find-one
  [pred coll]
  (loop [acc {} colls coll]
    (if (empty? colls)
      acc
      (if (apply pred [(first colls)])
        (first colls)
        (recur acc (rest colls))))))

(find-one #(= "A" (:name %)) my-list)

teamaverage02:09:40

Do you need the "apply"?

roberto02:09:54

good question, I don’t know. Will have to try without apply.

nikp02:09:06

Not 100% sure, but since filter returns a lazy seq wouldn't calling first on the result of filter only really calculate the function until the first result?

teamaverage02:09:17

Since it's only going to be a single map I think you can remove it - if it makes comprehrension better

roberto02:09:30

@nickp that makes sense

teamaverage02:09:43

@nikp: you mean would it always only return the first one?

teamaverage02:09:59

I don't think so cause you're rebinding the loop to the (rest coll)

roberto02:09:14

@teamaverage: I think he is referring to the more simpler (comp first filter)

roberto02:09:45

I’m inclined to think @nikp is right. Makes total sense.

grounded_sage02:09:34

Hi can anyone explain to me how to use Hiccup when inserting an image into the html? This is the function (image attr-map? src alt)

teamaverage02:09:35

so my suggestions of (comp first filter) wouldn't work

grounded_sage02:09:05

I'm having trouble understanding what attr-map? is.

roberto02:09:20

it is a map of attributes

roberto02:09:35

for example: {:class “my-css-class” :style “some css style”}

roberto02:09:57

ids, and other html attributes

roberto02:09:20

your event handlers would also go in there

roberto02:09:17

eg:

[image {:class “img”} “//src/to/image” “This is an image”]

grounded_sage02:09:34

not sure how the {:class "img"} part works as doing a class is usually {:.img}

teamaverage02:09:57

Hrm well I'm not sure as to the lazyness cause (filter odd? (range 10)) gives me the full list

teamaverage02:09:12

e.g. 1 3 5 7 9

teamaverage02:09:36

I would have thought it would have given me nothing until I tried to pull from that list

meow03:09:58

@teamaverage: I think filter works in chunks

meow03:09:35

But it is lazy

teamaverage03:09:40

aaaaaah that rings a bell

teamaverage03:09:49

Chunk size of 32 or something right

teamaverage03:09:13

So if I've got the above code and what you say about chunks is true but my list is greater than the chunk size, how do I get the rest of the list?

meow03:09:32

@teamaverage: don't worry about it - that's an underlying implementation detail that clojure takes care of

meow03:09:48

filter is lazy, that's all that matters in this context

meow03:09:10

it won't consume infinite resources

meow03:09:59

(first (filter odd? (range 10))) will be efficient

meow03:09:29

so will (first (filter odd? (range)))

meow03:09:18

so will (first (range))

meow03:09:04

hell, I had to add a doall the other day to avoid laziness where I needed side effects to be resolved

teamaverage03:09:18

@meow: I try not to, just curious is all : )

luxbock04:09:10

some should work just as well

escherize07:09:27

Is there a better (quick and dirty) way to annotate a function with pre/post and get a comment-y message with your error?

(defn invert-map [m]
  {:pre [(do "Must have unique values."
             (= (count m) (-> m vals set count)))]}
  (zipmap (vals m) (keys m)))