Reputation: 5301
I have started learning clojure. I am stuck at using let inside ->>
macro
The code is :
(defn make-summary [wordStr]
;// split string into words
(let [words (clojure.string/split wordStr #"[\[\]\(\),.\s+]")
;// convert words to lowercase.
lowerCaseWords (map clojure.string/lower-case words)]
;// remove stop words
(->> (remove-stop-words lowerCaseWords)
;// count the frequency of words
;// ---------- HERE IS THE PROBLEM ------------------------------
(let [totalWords (count )] ;// <--- HOW TO MAKE MACRO PUT THE THING HERE ???
(count-frequency)
;// sort on the basis of frequency
(sort #(> (get %1 1) (get %2 1)))
;// find the keywords
)
)))
I am stuck at the second let
inside the defn function.
How can i code it ?
Upvotes: 1
Views: 496
Reputation: 1077
You can use your original code with the as-> threading macro added in clojure 1.5 instead of inserting its argument to the first (->) or to the last (->>) position of each form, it lets you specify the position:
(as-> [1 2 3] x
(conj x 4)
(map inc x)) ;=> '(2 3 4 5)
I think, the advice is to use -> or ->> when you can and only fall back to as-> if this is not easily done. The summarise function by @Thumbnail is a nice example of the readability you get with ->>.
You can think of as-> as a convenient shorthand for the following code:
(let [x [1 2 3]
x (conj x 4)
x (map inc x)] x)
Here is the relevant part of your code written with as->:
(as-> (remove-stop-words lowerCaseWords) x
(let [totalWords (count x)] .....
Upvotes: 4
Reputation: 5301
It is not possible to have ->>
insert the argument at any place other than last item of the form. But this can be used in a trick to make it happen :
(defn make-summary [wordStr]
;// split string into words
(let [words (clojure.string/split wordStr #"[\[\]\(\),.\s+]")
;// convert words to lowercase.
lowerCaseWords (map clojure.string/lower-case words)]
;// remove stop words
(->> (remove-stop-words lowerCaseWords)
;// count the frequency of words
(fn [LCW] (let [totalWords (count LCW)] ;// <--- HOW TO MAKE MACRO PUT THE THING HERE ???
(count-frequency)
;// sort on the basis of frequency
(sort #(> (get %1 1) (get %2 1)))
;// find the keywords
)
))))
What i have done is wrapped the things inside the function, and now you can put the argument at any place.
Upvotes: 0
Reputation: 13473
Following @DiegoBasch's advice ...
If you're looking for
->>
macrothen the following might suit:
(defn summarise [text stop-words]
(->> text
(re-seq #"[a-zA-Z]+")
(map clojure.string/lower-case)
(remove stop-words)
frequencies
(sort-by (comp - val))
(map key)))
For examples
(summarise "Mary had a HUGE a lamb" #{})
("a" "mary" "had" "huge" "lamb")
(summarise "Mary had a HUGE a lamb" #{"huge"})
("a" "mary" "had" "lamb")
Notes
(set (map clojure.string/lower-case stop-words))
instead of
stop-words
in the remove
. Otherwise stop words with upper case
letters will be ineffective. Upvotes: 2