Fork me on GitHub
#beginners
<
2017-10-12
>
qle-guen09:10:13

hey, I got a list that looks like this '(true true false true) and another one like this: (:a :b :c :d) I need to keep only the elements from the second if the element from the first as the same index is true

qle-guen09:10:34

is there a function in clojure.core that could help me? Or do I have to invent the wheel here?

delaguardo09:10:02

(keep-indexed #(if (nth '(true true false true) %1) %2) '(:a :b :c :d)) something like this

schmee09:10:06

another suggestion:

user=> (def a '(true true false true))
#'user/a
user=> (def b '(:a :b :c :d))
#'user/b
user=> (remove nil? (map #(when %1 %2) a b))
(:a :b :d)

Sam H10:10:11

I ended up doing this:

cljs.user=> (filter (fn [[keep _]] (true? keep)) (map vector '(true false true) '(:a :b :c)))
([true :a] [true :c])

qle-guen12:10:00

ok thanks for your suggestions

noisesmith17:10:16

@U3L6TFEJF fyi (remove nil? (map ...)) can be replaced by (keep ...)

noisesmith17:10:25

oh, never mind, keep doesn’t take more args like map does, that’s too bad

newbo13:10:11

I am new to clojure and functional programming. I was doing some hackerrank example in clojure to build up my knowledge I was wondering could I get a some feedback. The test is to add up the amount of positive, negatives and zeros in a vector

newbo13:10:18

to begin with I wrote

newbo13:10:30

(def positives 0) (def negatives 0) (def zeroes 0) (doseq [item arr] (if (= item 0) (do (def zeroes (inc zeroes))) (do (if (neg? item) (do (def negatives (inc negatives))) (do (def positives (inc positives))) ) ) ) ) (println (format "%.5f" (float (fractional n positives))) ) (println (float (fractional n negatives))) (println (float (fractional n zeroes)))

newbo13:10:36

very java-esque

newbo13:10:46

but it was my first attempt

newbo13:10:51

then I re-wrote it to

newbo14:10:00

(def zeroes (count (filter #{0} arr))) (def positives (count (filter (fn [x] (pos? x)) arr))) (def negatives (count (filter (fn [x] (neg? x)) arr))) (println (format "%.5f" (float (fractional n positives)))) (println (float (fractional n negatives))) (println (float (fractional n zeroes)))

newbo14:10:05

much simpler

newbo14:10:22

but isnt it n^3 running time?

newbo14:10:55

Interest to understand where should I tihnk about to be able to filter a list list this but iterate once

donaldball14:10:29

When I want to do a thing over a seq but I’m not sure what the best fns to use are, I go to my old friend reduce

byron-woodfork14:10:03

^ same thing came to mind

sundarj14:10:08

(reduce
 (fn [[zeroes positives negatives] val]
   (prn zeroes positives negatives val)
   [(if (zero? val) (inc zeroes) zeroes)
    (if (pos? val) (inc positives) positives)
    (if (neg? val) (inc negatives) negatives)])
 (repeat 3 0)
 [0 0 -1 2 2 -3 0])
@diarmuidmoloney

donaldball14:10:18

Another thing you might try is to separate the two things that are going on: simplifying the values from the domain of all numbers to the domain of #{:pos :neg: zero}, then counting the frequencies of those values

wilcov14:10:44

This might be something that gets you in the right direction:

(defn countNumTypes
        [acc num]
        (let [[pos neg zero] acc]
          (cond
            (> num 0) [(inc pos) neg zero]
            (< num 0) [pos (inc neg) zero]
            (= num 0) [pos neg (inc zero)])))

(reduce countNumTypes [0 0 0] [0 1 -1])

returns: [1 1 1]

rauh16:10:54

@diarmuidmoloney 1. Extract the function which produces 0, 1, -1, call it sign or signum. 2. Call (frequencies (map signum your-number))

newbo16:10:42

let me have play around, thanks for the code reviews 😄

yogidevbear19:10:00

Hi 👋 Hoping someone can help me out with this. If I had a collection like this:

(def example [{:name "Foo" :someCount 18} {:name "Bar" :someCount 24}])
What would be the "best" way of using (reduce + [insert logic here]) to get a sum of the values in :someCount?

jjfine19:10:51

hey, there's a function called comp that takes multiple functions and returns a function that calls each of them in reverse order (reduce (comp + :someCount) example)

yogidevbear19:10:51

What about doing something along the lines of (reduce (fn [result coll] (+ result some-selector-here)) 0 example)?

yogidevbear19:10:36

I think I'm missing an understanding of how to get the :someCount selector within coll

dpsutton19:10:42

yogidevbear, when reducing over a collection, the reducing function gets called with the accumulator as the first param and each element of the collection as the second element

dpsutton19:10:09

so our signature is (fn [count-so-far this-map] (+ count-so-far (:someCount this-map)))

dpsutton19:10:06

in the alternative, you can turn your collection into numbers (map :someCount collection) and then (reduce + this-new-collection) or (apply + this-new-collection)

yogidevbear19:10:06

Thanks @dpsutton 👍 It was the (:key-name coll) that I wasn't quite grokking

yogidevbear19:10:16

Doing (reduce (fn [result coll] (+ result (:someCount coll))) 0 example) should do the trick

yogidevbear19:10:15

Yup, works like a treat. So my next question is, is there a "better" way? If so, what and why is it considered better?

noisesmith19:10:10

an alternate that might perform better is (transduce (map :someCount) + example)

sundarj19:10:15

how about (transduce (map :someCount) + 0 [{:name "Foo", :someCount 18} {:name "Bar", :someCount 24}])

sundarj19:10:19

gdi noisesmith

noisesmith19:10:39

@sundarj the 0 is redundant, as (+) returns 0

sundarj19:10:53

good point

noisesmith19:10:20

also (+ n) returns n

user=> (transduce (map :someCount) + [{:someCount 1} {:someCount 2}])
3

noisesmith19:10:35

the transduce version is also much clearer and cleaner (to my eye)

yogidevbear20:10:33

Wow! That is pretty sweet

yogidevbear20:10:59

I'm not onto transducers yet, but it's good to see that in action

vinnyataide21:10:20

once again... I look at a new rich hickey talk, look back at my code... and ask what the hell I was doing

yogidevbear21:10:46

Another example related to filtering based on a value existing within a vector in a hashmap. Given (def example [ { :name "Foo" :someVector ["String A" "String B" "String C"] } { :name "Bar" :someVector [] } ] ) How would I retrieve the hashmaps where :someVector constains a string (e.g. "String B" to return Foo hashmap)? I'm leaning towards a solution like (filter #(find "String B" (:someVector %)) example), but that gives me a ClassCastException

noisesmith21:10:38

find expects a hash-map

noisesmith21:10:57

you can use #(contains? #{"String B"} (:someVector %)) or as a shorthand, (comp #{"String B"} :someVector)

noisesmith21:10:23

oh wait, you want to know if “String B” is anywhere in there, so that won’t work

noisesmith21:10:12

(contains? (set (:someVector %)) "String B")

noisesmith21:10:32

or, use .indexOf

b-paul21:10:56

Hello, all, I'm working on my first cljs project, and I've added [cheshire "5.8.0"] to project.clj :dependencies, but the figwheel output doesn't seem to include it (after restarting)

b-paul21:10:34

I did get output from leiningen apparently downloading the new dependencies. Figwheel reads the config as valid, but then says "Failed to compile ... No such namespace: cheshire.core"

noisesmith21:10:52

why would cljs be able to use cheshire?

noisesmith21:10:18

I guess you could use it in a macro but I can’t imagine that would ever be useful

b-paul21:10:01

@noisesmith yeeeah, that would be it.

noisesmith21:10:52

to use json from cljs I think the preferred thing is using interop since javascript can do JSON natively

b-paul21:10:29

Did that at the start. I was googling for JSON-to-native data structures when I found cheshire

noisesmith21:10:08

oh- you want the opposite direction - the better option is to use goog.object I think

noisesmith21:10:15

either just using goog.object on the thing, or using the functions there to construct the clojure data you need

b-paul21:10:47

Okay. I'd definitely rather not rely on these functions throughout, so I might do the second

b-paul22:10:36

Maybe I'm just missing the simple trick though? -- https://cljs.github.io/api/cljs.core/js-GTclj

noisesmith22:10:40

I bet there are helpful libraries but I’ve heard people who know more about cljs than I do talk about the limitations / drawbacks of using eg. js->clj

sundarj22:10:47

use transit

b-paul22:10:21

I'm trying to ease this in gently

sundarj22:10:18

transit can parse arbitrary json

sundarj22:10:37

and it's fast

sundarj22:10:41

if i recall correctly that is

yogidevbear22:10:52

@noisesmith, (filter #(contains? (set (:someVector %)) "String B") example) worked perfectly, thank you. I tried playing around with filter and .indexOf, but couldn't quite get it to work. #(contains? (set ... is quite nicely readable though 🙂

bfabry22:10:04

transit does seem pretty reasonable

cljs.user=> (t/read (t/reader :json) "{ \"foo\": 1, \"bar\": \"bash\", \"baz\": [{\"string\": \"key\"}]}")
{"foo" 1, "bar" "bash", "baz" [{"string" "key"}]}
cljs.user=>

bfabry22:10:26

js->clj also seems to work but its documentation indicates you're better off using transit

b-paul22:10:40

Good to know

bfabry22:10:54

cljs.user=> (js->clj (JSON/parse "{ \"foo\": 1, \"bar\": \"bash\", \"baz\": [{\"string\": \"key\"}]}"))
                      ⬆
WARNING: No such namespace: JSON, could not locate JSON.cljs, JSON.cljc, or JavaScript source providing "JSON" at line 1
                      ⬆
WARNING: Use of undeclared Var JSON/parse at line 1
{"foo" 1, "bar" "bash", "baz" [{"string" "key"}]}

noisesmith22:10:50

@bfabry I think that nees to be js/JSON

bfabry22:10:15

cheers, I figured there was some cljs knowledge I was missing to kill the warnings

b-paul22:10:43

I'd love to figure out why my core.cljs is locked every time I have a compile error and I have to restart figwheel to be able to save the file again.

b-paul22:10:15

I'm on Windows, and this seemed promising https://github.com/bhauman/lein-figwheel/issues/604, except it looks like it was only on the Linux emulation layer for that user