Fork me on GitHub
#beginners
<
2023-01-28
>
skylize00:01:44

Interesting function I just wrote that made me feel clever: If you reverse the output of split-with and concat the result, you get a rotation of the input collection with a targeted value moved to the head.

(defn rotate-with [f xs]
  (apply concat (reverse (split-with f xs))))

(let [xs [0 1 2 3 4 5]]
  (rotate-with #(not= 3 %) xs))
; =>
(3 4 5 0 1 2)

❤️ 2
skylize04:01:45

Perhaps the predicate should be wrapped in complement as well, since otherwise the predicate is backward from what seems intuitive for identifying the target entry.

(defn rotate-with [pred xs]
  (apply concat (reverse
                 (split-with (complement pred) xs))))

(let [xs [0 1 2 3 4 5]]
  (rotate-with #(= 3 %) xs))
; =>
(3 4 5 0 1 2)

2
noob.clj14:01:00

Hey all, I am trying to solve advent of code problems using clojure. Here is a small snippet of how I am using loop for one of the questions:

(loop [coord [1 1] dirs `(\U \L \L)]
  (if (empty? dirs)
    coord
    (recur (move coord (first dirs)) (rest dirs))))
So basically the logic is I have to pass coord and first direction from list of dirs. Then I have to take the response and keep repeating that until I run out of directions. Is there a better way to do this? Like this is basically some form of “dynamic threading macro” where the values keep flowing downwards until they run out. I wonder if there is a method or something to make this easier to read. Note: This is from aoc 2016 day2

pithyless14:01:56

I’m away from the computer but this looks like: (reduce (fn [coord dir] (move coord dir)) [1 1] dirs)

🤯 2
noob.clj14:01:27

ohh it worked 🙂 awesome thanks. I should’ve paid more attention when reading docs for reduce. I’ve only used it for summing array up until now 😛 but the doc clearly explains that any function with 2 params will work there.

skylize14:01:04

Side note: We generally use the plain quote ' (apostrophe) or the function it expands to (quote ...) instead of the syntax quote ` (backtick), unless specifically needing the extra features of a syntax quote.

thanks3 2
pithyless15:01:39

It’s probably also good to mention that if you’re providing this initial collection I would have used a vector instead (unless you have a very good reason why you want it to be a list).

noob.clj15:01:31

I don’t have a strong reason to use list. However, I thought Vector is like an ArrayList and List is like LinkedList. So vector is better for random access and list is better for edge expansion or shrinking. For sequential access they both should perform the same, no?

pithyless15:01:20

For sequential access they are equivalent but if your sequence doesn’t need to be lazy you will find it more idiomatic to default to vectors. For example, in other lisps a let would use a list for defining bindings but in Clojure the bindings are wrapped in a vector. It’s not because of random access semantics, but just the convention that was chosen. IMO, you’ll find it easier if you default more to vectors, because then lists become more visible in the code: „hmm, why is this a list? is it for laziness? or perhaps for fast conj to beginning of collection? etc”

popeye20:01:28

why this is failing?

(apply map #(.toLowerCase %) [["M" "M" "M"] ["C" "M"] ["X" "C"] ["I" "X"]])

hiredman20:01:56

Rewrite it to what it would be without apply (rewrite the function and the input to match)

hiredman20:01:53

Not that a solution, but will be illustrative of the issue

hiredman20:01:46

The error you get (I haven't run it but I believe you'll get an arity error for the anonymous function being passed to map) is also informative

popeye20:01:31

got

(map #(.toLowerCase %) [["M" "M" "M"] ["C" "M"] ["X" "C"] ["I" "X"]])
; Error printing return value (IllegalArgumentException) at clojure.lang.Reflector/getInstanceField (Reflector.java:397).
; No matching field found: toLowerCase for class clojure.lang.PersistentVector

hiredman20:01:21

I meant the error with the original code

popeye20:01:32

(apply map #(.toLowerCase %) [["M" "M" "M"] ["C" "M"] ["X" "C"] ["I" "X"]])
; Error printing return value (ArityException) at clojure.lang.AFn/throwArity (AFn.java:429).
; Wrong number of args (4) passed to: four-clojure.hard.core/eval9049/fn--9050
clj꞉four-clojure.hard.core꞉> 

hiredman20:01:52

And you didn't rewrite the input to what you expect apply to do when you stripped out apply

popeye20:01:19

i did not get when you said stripped out reply

hiredman20:01:36

Which is where your issue is, it seems like you expect apply to concat, but apply is not concat

hiredman20:01:43

(apply map f [[1 2] [3 4]]) -> (map f [1 2] [3 4])

hiredman20:01:21

But you want (map f [1 2 3 4])

wilkerlucio21:01:14

or, to keep the same data structure, you can: (map (fn [c] (map #(.toLowerCase %) c)) [["M" "M" "M"] ["C" "M"] ["X" "C"] ["I" "X"]])