Fork me on GitHub
#beginners
<
2016-02-26
>
jack_liang02:02:35

hi, i have a question , so i have a hashmap of words->word_count, after the map is created and keys/values are inserted, i printed the map and everything was fine, however after i used sort-by, keys are fine but values come back as nil, any ideas why?

jack_liang02:02:52

specifically it happens after this line

jack_liang02:02:53

(def sorted(sort-by val > unique-map))

jack_liang02:02:25

im trying to sort my hashmap by value in descending order

seancorfield04:02:47

Hi @jack_liang ! If you look at the result of (sort-by val > unique-map) you'll see it's a sequence of pairs -- not a hash map... If you're trying to index it by a word, that's why you're getting nil back

seancorfield04:02:08

boot.user=> (def m {:a 2 :b 4 :c 1 :d 3})
#'boot.user/m
boot.user=> (sort-by val > m)
([:b 4] [:d 3] [:a 2] [:c 1])
boot.user=>

jack_liang04:02:06

so how would i go about iterating it, so to speak

jack_liang04:02:57

id have to use loop and nth?

seancorfield04:02:59

Not sure what you're asking -- it's a sequence of pairs already.

seancorfield04:02:19

What are you trying to do with the sorted word couunts?

jack_liang04:02:31

i want the top 3 results

seancorfield04:02:34

(remember: Clojure is all about holistic processing of collections)

seancorfield04:02:53

So (take 3 sorted) will give you the first three entries

seancorfield04:02:12

That's your top three.

jack_liang04:02:13

would that return a sequence of pairs also?

seancorfield04:02:31

You want just the words, no counts?

jack_liang04:02:52

both words and count

seancorfield04:02:13

Then that's what you've got (take 3 sorted)

seancorfield04:02:10

Do you want it as a hash map again? (where it will be unordered by definition -- but will only contain three key/value pairs)

jack_liang04:02:34

im assumin theres a function for converting a sequence to hashmap, but given that i have the sequence, how do i go about calling on each pair?

seancorfield04:02:50

(into {} (take 3 sorted))

jack_liang04:02:02

my thoughts are telling me something like (def element (nth sequence index))

seancorfield04:02:04

You "pour" your sequence of pairs "into" an empty hash map

seancorfield04:02:32

What do you want to do with each pair (in order) then?

jack_liang04:02:23

at this point, the count would just be to tell me which word is seen 1st,2nd and 3rd most. Id use the words for comparisons

seancorfield04:02:35

I don't understand what you want beyond the sequence of word / count pairs then, sorry.

jack_liang04:02:56

its ok, i get that most of the time what comes out of my mouth doesnt make sense

seancorfield04:02:04

Well, (take 3 sorted) gives you the 1st word and its count, then the 2nd word and its count, and finally the 3rd word and its count...

jack_liang04:02:14

lets say contents of (take 3 sorted) is {[1 a],[2 b],[3 c]}, how do i reach the first pair?does that question make sense?

jack_liang04:02:15

nvm, turning it hashmap works out fine

jack_liang04:02:35

i take it back, how would i access each pair?

seancorfield04:02:26

What are you trying to do with those pairs?

seancorfield04:02:36

Step back and think about the collection as a whole...

seancorfield04:02:54

(because we don't usually "loop over elements" in Clojure)

jack_liang04:02:47

how do i get out of the habit of thinking about looping over elements and into thinking about collection as a whole?

seancorfield04:02:21

It's a step up the abstraction ladder...

seancorfield04:02:03

...What are you ultimately doing with the top three words (and counts)? Printing them? Doing something else with them?

jack_liang04:02:39

for the top 3 words, i want to pull out sentences that contain those words

seancorfield04:02:01

(and, yes, this "change of gears" is the hardest part of moving from imperative to functional programming)

seancorfield04:02:21

OK, so you have a sequence of sentences? And they're strings?

seancorfield04:02:57

And do you care about the counts?

seancorfield04:02:19

(or just the three top words in any order?)

jack_liang04:02:27

yes order matters

seancorfield04:02:39

Because... how does the order affect the result?

jack_liang04:02:33

its suppose to help structure the resulting string

seancorfield04:02:58

Can you explain how it would structure that string?

jack_liang04:02:47

i probably could have about hour ago

jack_liang04:02:00

ill take it one step at a time and try with just the words first

jack_liang04:02:37

without order i mean

seancorfield04:02:53

You have a sequence of sentences? And you want to produce a single string as a result? Somehow controlled by which sentences contain which words?

jack_liang05:02:45

well the single string isnt one sentence, its concatenation of my chosen number of sentences , in this case 3

jack_liang05:02:55

overall the end result is a summariser

seancorfield05:02:17

How many sentences do you start with?

seancorfield05:02:39

I know you ended up with 3 words, but I'm unclear how you use those words to select sentences...

jack_liang05:02:13

i may have to rethink this

jack_liang05:02:28

thanks for the info, goodnight

jeremyraines06:02:00

let’s say I’m testing a function which calls a namespaced function. How can I stub the latter? For example:

;; in myapp.core
(defn first-product []
  (first (db/products))

;;in myapp.core-test
;; somehow stub (db/products) to return [{:name “foo”}]

(deftest first-product-test
  (is = (first-product) {:name “foo”))

jeremyraines06:02:49

I don’t think it works with the namespace

solicode06:02:42

Really? I think it should

jeremyraines06:02:18

hmm - maybe it’s important to note that it comes in through a require in the namespace under test

jeremyraines06:02:40

I needed to refer to it by its real namespace not its alias in the namespace that requires it

jeremyraines06:02:57

that works now — thanks

jeremyraines06:02:18

(minus unrelated problem with that code, as per usual)

mostr19:02:45

folks, am I missing something or there really is no way to “listen” for future completion in clojure? I mean, not block with deref but just be “told” that future completed with given result?

jonahbenton20:02:07

hey @mostr how do you envision being told? what would the implications of completion be?

mostr20:02:28

not sure, but I was expecting something like in e.g. Scala where I can do things like

f onComplete {
  case Success(posts) => // do stuff with posts
  case Failure(t) => println("An error has occured: " + t.getMessage)
}

mostr20:02:20

because now when I run something in future I cannot tell: “do this when this future returns stuff” while letting current thread doing other things, right?

mostr20:02:30

hmm, but now I think this might be done with core.async watches…

mostr20:02:48

but again it looks like plumbing stuff, so I’m pretty sure I misunderstand some clojure-specific fundamentals here simple_smile

jonahbenton20:02:49

say more? it may be that thinking about it in terms of data flow rather than specifically in terms of syntax may be helpful. you have some work you want done asynchronously, and some other work should consume the first batch and do some follow on work, and/or report on failure...and perhaps there is follow on work after that? there are a lot of ways of implementing the data flow- could put the entire processing chain into a future, e.g. (future (-> (make-posts) (do-stuff-with-posts) (do-more-stuff))) if you want ultimately to be able to capture results, or could use a couple of go-loops to do work and a channel for communication...

mostr20:02:52

(defn add-100-async [x]
  (future (Thread/sleep 6000) (prn "Future is about to finish") (+ x 100)))

(prn "Start future")
(add-100-async 20)  ; how to get result and do other stuff with it
(prn "Do other (sync) stuff")
(Thread/sleep 2000)
(prn "Done")

mostr20:02:16

@jonahbenton: simple use case, call function that returns future, then do some other work. How to get add-100-async result and work with it?

jonahbenton21:02:56

@mostr sure, so, add-100-async returns a future. if you want to do something with the results, you'll need to capture the return value. you can hand it to another future, e.g.

jonahbenton21:02:07

(def f (add-100-async 1)) (future (let [results @f] (println "future completed. wait some more") (Thread/sleep 2000) (println (str "results plus 200: " (+ results 200))))))

jonahbenton21:02:44

but it may also make sense to put all of the work into a single future, if the ultimate results are io, rather than a value to be further consumed

rauh21:02:38

@mostr: You aren't missing anything. You really can't with clojure's futures. They're tiny wrappers around Java's futures and they don't provide a callback

rauh21:02:03

You'd have to use other libraries all the way down. Like zack tellmans' aleph. Or RxJava/RxClojure

rauh21:02:43

But in clojure land we aren't too fond of callbacks and the JVM performs just fine with LOTS of threads.