Fork me on GitHub
#beginners
<
2022-12-10
>
Vernon03:12:12

Hi all, I just started learning Clojure and Iā€™m wondering if wrapping a function, in order to rethread the received argument is bad practice?

(->> ["This" "is" "," "," "," "my" "example" "vector" "."]
     (map (fn [x] (if (or (= x ",") (= x ".")) x (str " " x))))
     (apply str)
     ;; Here I wrap the clojure.string/replace function, so I can pass the
     ;; argument in from the front. Is this a bad thing to do?
     ((fn [x] (clojure.string/replace x #",{2,}" ""))))

skylize03:12:31

I would go even one step further: Pull that function out and give it a name so You-in-6-months can still figure out what it is supposed to do, without having to be a human compiler.

(let [remove-2+-commas (fn [x] (str/replace x #",{2,}" ""))
      add-spaces (fn [x]
                   (if (or (= x ",") (= x ".")) x
                       (str " " x)))]
  (->> ["This" "is" "," "my" "example" "vector" "."]
       (map add-spaces)
       (apply str)
       remove-2+-commas))

Vernon03:12:08

@U90R0EPHA Thats what I was thinking. Thanks for the example!

skylize04:12:25

@UP82LQR9N. A "top level" as-> could work here

(as-> m x
  (map (fn [x] ...) x)
  (apply str x)
  (clojure.string/replace x #",{2,}" ""))
But large portions of the community would tag that as "not idiomatic"; and I don't think it really improves anything over the anonymous function anyway. The more common usage, where at-> is used inline, would not work here because of using ->> instead of ->, which does not thread into the correct slot of the at-> macro..
(->> []
  (map (fn [x]))
  (apply str)
  ;; šŸ’£ Unresolved symbol x, because trying to thread
  ;;  in at the end, when value needs to go in at beginning.
  (as-> x (clojure.string/replace x #",{2,}" "")))

šŸ‘ 1
seancorfield05:12:06

Another possibility @U04D4J04PFW:

(-> ["This" "is" "," "," "," "my" "example" "vector" "."]
    (->> (map (fn [x] (if (or (= x ",") (= x ".")) x (str " " x))))
         (apply str))
    (clojure.string/replace #",{2,}" ""))
But I agree with @U90R0EPHA that naming those subfunctions is a much clearer approach.

šŸ‘ 2
1
Vernon05:12:59

Noted, thanks @U04V70XH6 šŸ™

kpav19:12:28

Does into return a lazy sequence? I am pretty sure I read that somewhere but I can't find any info about it when searching -- modified example from the clojure.data.csv docs,. I'd like to turn each column into a lazy set

(defn read-column
  [reader column-index]
  (let [data (csv/read-csv reader)]
    (->> data
         (map #(parse-long (nth % column-index)))
         (into #{}))))

Alex Miller (Clojure team)20:12:17

well first, sets aren't lazy and second, into puts elements into the collection you give it, which here is a set

kpav20:12:49

Ah right, that makes sense