2

I'm writing a function in clojure, that takes in 2 arguments (both are lists), and iterates over vehicles by recursion, until the vehicle list becomes empty. The function is like:

(defn v [vehicles locs]
    (if (= (count vehicles) 0)
        nil
        (if (> (count vehicles) 0)
            (split-at 1 locs)
            (v (rest vehicles) (rest locs))
        ))
    )

So, if I give the input as (v '(v1 v2 v3) '([1 2] [2 3] [4 2] [5 3])), then I want the output as [([1 2]) ([3 4]) ([5 6] [6 7])]. I know that the statement (v (rest vehicles) (rest locs)) is not executing because it's taking it in the else case i.e., when count(vehicles) not > 0. I want to know how can I make this statement be executed in the same if block, i.e., in (if (> (count vehicles) 0)

2
  • Take a look at when. Commented Oct 22, 2014 at 5:51
  • @Mark Thanks! Is there something like break? Because while iterating in the end it reaches (if (= (count vehicles) 0) and then prints nil only. Commented Oct 22, 2014 at 5:58

3 Answers 3

3

It sounds like you're trying to do something like this:

(defn v [vehicles locs]
  (if (seq (rest vehicles))
    (concat  [[(first locs)]] (v (rest vehicles) (rest locs)))
    [locs]))
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Is there a way I could get the output as ((v1 [1 2]) (v2 [0 2] [3 2])), if I give the input: (v '(v1 v2) '([1 2] [0 2] [3 2]))?
2

When you are using recursion and need to return some result of execution there is good approach to accumulate all of your recursion step's results in one holder variable. Here result is such a holder:

(defn v [vehicles locs]
  (if (empty? vehicles)
    nil
    (loop [result [] vs vehicles ls locs]
      (if (= 1 (count vs))
        (conj result ls)
        (recur (conj result (first ls)) (rest vs) (rest ls))))))

It works like this:

(v '(v1 v2 v3) '([1 2] [2 3] [4 2] [5 3]))
=> [[1 2] [2 3] ([4 2] [5 3])]

If you really need to wrap location one-element vectors (but actually it seems like a strange requirement) then try the following:

(defn v [vehicles locs]
  (if (empty? vehicles)
    nil
    (loop [result [] vs vehicles ls locs]
      (if (= 1 (count vs))
        (conj result ls)
        (recur (conj result (list (first ls))) (rest vs) (rest ls))))))

1 Comment

No need for an accumulator in a very simple case like this one, see my answer. It could be made lazy trivially too.
1

You can write multiple statements in if branches with a do form:

(if (= 1 (count vs))
  (do
    (conj result ls)
    (recur (conj result (first ls)) (rest vs) (rest ls)))
  :else)

If you don't need else branch it's convenient to use when macro:

(when (= 1 (count vs))
  (conj result ls)
  (recur (conj result (first ls)) (rest vs) (rest ls)))

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.