Ashish Negi
Ashish Negi

Reputation: 5301

Using let inside ->> macro

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

Answers (3)

KIMA
KIMA

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

Ashish Negi
Ashish Negi

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

Thumbnail
Thumbnail

Reputation: 13473

Following @DiegoBasch's advice ...

If you're looking for

  • the words in decreasing order of frequency of use
  • eliminating stop words and
  • exploiting the ->> macro

then 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

  • The function detects words as sequences of letters instead of detecting specific separator characters. You can reverse this change if you prefer.
  • I'd be inclined to make sure that the stop words too are lower case: use (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

Related Questions