0

I'm relatively new to Clojure and have been working through 4Clojure. I'm working on problem 31, Pack a Sequence, http://www.4clojure.com/problem/31#prob-title. The goal is to pack consecutive duplicates into sub-lists. I know this can be achieved using (partition-by ...) but I wanted to attempt writing it out in full using (loop ... (recur ...)). My attempt is as follows:

(defn my-subpack
[paramSeq]
;Track the output sequence
;Track the current sub sequence
;Track the next input value to consider
(loop [outSeq  []
     currSub (vector (first paramSeq))
     inSeq   (rest paramSeq)]
    ;If the inSeq is empty then we return outSeq
    (println (empty? inSeq))
    (if (empty? inSeq)
      outSeq)
    ;If the next value from inSeq is in the currSub then we add it to it
    (if (= (first currSub) (first inSeq))
      (recur outSeq (conj currSub (first inSeq)) (rest inSeq))
      (recur (conj outSeq currSub) (vector (first inSeq)) (rest inSeq)))
    ))

The program seems to get stuck in an infinite loop so I ran it through my IDE's debugger. It appears that when inSeq is empty the if statement to return outSeq does not get run. It is skipped over as if (empty? inSeq) returns false. Below I've included a screenshot of the IDE when the infinite loop begins. Notice that (count inSeq) returns 0 in the expression evaluator but the debugger shows it as having a count of 1. Here is the IDE when Infinite Loop begins. Count shows 0 in expression evaluator but it also shows 1 in debugger.

enter image description here

It feels likely to me I've made some huge oversight but I just amn't experienced enough to see it yet!

1
  • Your first if there is a no-op. It does not work like in imperative programming. It must must be the last operation in a form to return. Commented Aug 15, 2018 at 9:22

1 Answer 1

1

The issue is that when inSeq is empty, the machine just does nothing and proceeds to the next statement (which does recur in both cases). What you probably want is to return outSeq as the result of the loop expression if inSeq is empty:

(if (empty? inSeq)
  outSeq
  ;; If the next value from inSeq is in the currSub then we add it to it
  (if (= (first currSub) (first inSeq))
    (recur outSeq (conj currSub (first inSeq)) (rest inSeq))
    (recur (conj outSeq currSub) (vector (first inSeq)) (rest inSeq))))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.