user1050817
user1050817

Reputation: 965

Weird behaviour binding in loop recursion

I'm learning Clojure, and I'm trying to solve the Problem 31: Write a function which packs consecutive duplicates into sub-lists.

(= (__ [1 1 2 1 1 1 3 3]) '((1 1) (2) (1 1 1) (3 3)))

I know I can solve this using identity, and in a functional way, but I want to solve it using recursion, because I've not well established this idea in my brain.

My solution would be this:

(defn packing [lista]
  (loop [[fst snd :as all] lista    mem []    tmp '(fst)]

   (print "all is   "    all   "\n\n") ;; something is wrong; it always is an empty list

   (if (seq? all)
     (if (= fst snd)
         (recur (rest all) mem (cons snd tmp))
         (recur (rest all) (conj mem tmp) (list snd)))
    (seq mem))))

My idea is a recursive loop always taking the first 2 items and comparing. If they are the same number, I include this inside a temporary list tmp; if they're different, I include my temporary list inside men. (This is my final list; a better name would be final_list.)

Because it compares the first 2 items, but at the same time it needs a recursive loop only bypassing the first item, I named the entire list all.

I don't know if the logic is good but inclusive if this was wrong I'm not sure why when I print.

 (print "all is   "    all   "\n\n") I receive an empty list

Upvotes: 1

Views: 144

Answers (2)

clagccs
clagccs

Reputation: 2324

in your code all isn't empty..only happen than is an infinite loop and you always see a empty list...in the firsts lines you can see than it works like expected..

the mistake is in (seq? all) because a empty list is a seq too... try (seq? '()) and return true...then you do a empty loop you need change this for (empty? all) your code would be other mistake is '(fst) because it return the simbol fst and not the value...change it for (list fst)

(defn badpacking [lista]
  (loop [[fst snd :as all] lista    mem []    tmp (list fst)]
    (if (empty? all)
       (seq mem)
       (if (= fst snd)
           (recur (rest all) mem (cons snd tmp))
           (recur (rest all) (conj mem tmp) (list snd))))))

Upvotes: 0

Alex Taggart
Alex Taggart

Reputation: 7825

A few points:

  • '(fst) creates a list containing a symbol fst, not the value of fst, this is one of the reasons to prefer using vectors, e.g., [fst]
  • you should avoid assuming the input will not be empty
  • you can use conj for both lists and vectors
  • destructuring is nestable
(defn packing [coll]
    (loop [[x & [y :as more] :as all] coll
           result                     []
           same                      '()]
    (if all
     (if (= x y)
       (recur more result (conj same x))
       (recur more (conj result (conj same x)) '()))
     result)))

Upvotes: 1

Related Questions