Search code examples
clojureseqlazy-sequences

How to turn a clojure lazy-seq of strings into separate strings?


I have a random amount of strings in a seq that I'm trying to "destructure"? into separate strings, while also dropping the last string in the seq.

("a" "b" "c") -> "a" "b"

I tried a few things, and the closest I've got is with (apply str (drop-last args)), but as you probably know, this turns the seq of strings into a single string.. "ab"

How do I do this?


Solution

  • It sounds like you'd use sequential destructuring:

    (def col-of-strings '("a" "b" "c" "d" "e"))
    
    (let [ [a b c & etc ]  col-of-strings
           last            (drop-last etc) ]
      (println "a=" a " b=" b " c=" c " and etc=" etc " last=" last))
    

    which prints

    a= a  b= b  c= c  and etc= (d e)  last= (d)
    

    Another option would be to remove the last string first, then destructure:

    (let [ col-minus-last  (drop-last col-of-strings)
                  [ a b c & etc]  col-minus-last ]
      (println "a=" a " b=" b " c=" c " etc=" etc))
    

    which prints

    a= a  b= b  c= c  etc= (d)
    

    If you really don't know how many elements are in your collection then I think your best bet may be to use a loop:

    (loop [ c  (drop-last col-of-strings) ]
      (let [s  (first c) ]
        (println "s=" s)
        (if (nil? s)
          nil
          (recur (rest c)))))
    

    EDIT

    OP says he wants to pass a variable number of strings for processing. In that case it sounds like recursively walking down the list would be appropriate:

    (defn vararg-func [ s & etc]
      (println "s=" s)
      (if (nil? s)
        nil
        (recur (first etc) (rest etc))))
    

    But since OP says he already has a lazy sequence of strings (filenames) I think the easiest way to handle it is to simply pass the sequence into the function and loop over it:

    (defn seq-func [ s ]
      (loop [ str     (first s)
              usw     (rest s) ]
        (println "str=" str)
        (if (nil? str)
          nil
          (recur (first usw) (rest usw)))))
    

    which is very similar to the earlier code.