Trying to use threading macros and getting error - clojure

This is my first attempt at using the thread-first macro
My goal is to put the vector through map and then filter
(-> [1 2 3 4 5 6 7 8]
(filter (fn [x] (<= x 3)))
(map (fn [x] (* 10 x))))
I am getting
Error: function (x){return (10 * x);
}is not ISeqable
at Error (<anonymous>)
at cljs.core.seq
What does it mean?

You would have to use ->>. The doc:
Threads the expr through the forms. Inserts x as the
last item in the first form, making a list of it if it is not a
list already. If there are more forms, inserts the first form as the
last item in second form, etc.
Your threaded calls there are filter and map which both take the list as second param. -> puts them as first parameter. So your code there would look like this: (filter [1 2 3 4 5 6 7 8] (fn [x] (<= x 3))), your function is no seq, hence the error.

Related

Good way in clojure to map function on multiple items of coll or seqence

I'm currently learning Clojure, and I'm trying to learn how to do things the best way. Today I'm looking at the basic concept of doing things on a sequence, I know the basics of map, filter and reduce. Now I want to try to do a thing to pairs of elements in a sequence, and I found two ways of doing it. The function I apply is println. The output is simply 12 34 56 7
(def xs [1 2 3 4 5 6 7])
(defn work_on_pairs [xs]
(loop [data xs]
(if (empty? data)
data
(do
(println (str (first data) (second data)))
(recur (drop 2 data))))))
(work_on_pairs xs)
I mean, I could do like this
(map println (zipmap (take-nth 2 xs) (take-nth 2 (drop 1 xs))))
;; prints [1 2] [3 4] [5 6], and we loose the last element because zip.
But it is not really nice.. My background is in Python, where I could just say zip(xs[::2], xs[1::2]) But I guess this is not the Clojure way to do it.
So I'm looking for suggestions on how to do this same thing, in the best Clojure way.
I realize I'm so new to Clojure I don't even know what this kind of operation is called.
Thanks for any input
This can be done with partition-all:
(def xs [1 2 3 4 5 6 7])
(->> xs
(partition-all 2) ; Gives ((1 2) (3 4) (5 6) (7))
(map (partial apply str)) ; or use (map #(apply str %))
(apply println))
12 34 56 7
The map line is just to join the pairs so the "()" don't end up in the output.
If you want each pair printed on its own line, change (apply println) to (run! println). Your expected output seems to disagree with your code, so that's unclear.
If you want to dip into transducers, you can do something similar to the threading (->>) form of the accepted answer, but in a single pass over the data.
Assuming
(def xs [1 2 3 4 5 6 7])
has been evaluated already,
(transduce
(comp
(partition-all 2)
(map #(apply str %)))
conj
[]
xs)
should give you the same output if you wrap it in
(apply println ...)
We supply conj (reducing fn) and [] (initial data structure) to specify how the reduce process inside transduce should build up the result.
I wouldn't use a transducer for a list that small, or a process that simple, but it's good to know what's possible!

What separates a transformer from a reducer ? - Clojure

From what I gather a transformer is the use of functions that change , alter , a collection of elements . Like if I did added 1 to each element in a collection of
[1 2 3 4 5]
and it became
[2 3 4 5 6]
but writing the code for this looks like
(map inc)
but I keep getting this sort of code confused with a reducer. Because it produces a new accumulated result .
The question I ask is , what is the difference between a transformer and a reducer ?
You are likely just confusing various nomenclature (as the comments above suggest), but I'll answer what I think is your question by taking some liberties in interpreting what you mean to be reducer and transformer.
Reducing:
A reducing function (what you probably think is a reducer), is a function that takes an accumulated value and a current value, and returns a new accumulated value.
(accumulated, current) => accumulated
These functions are passed to reduce, and they successively step through a sequence performing whatever the body of the reducing function says with it's two arguments (accumulated and current), and then returning a new accumulated value which will be used as the accumulated value (first argument) to the next call of the reducing function.
For example, plus can be viewed as a reducing function.
(reduce + [0 1 2]) => 3
First, the reducing function (plus in this example) is called with 0 and 1, which returns 1. On the next call, 1 is now the accumulated value, and 2 is the current value, so plus is called with 1 and 2, returning 3, which completes the reduction as there are no further elements in the collection to process.
It may help to look at a simplified version of a reduce implementation:
(defn reduce1
([f coll] ;; f is a reducing function
(let [[x y & xs] coll]
;; called with the accumulated value so far "x"
;; and cur value in input sequence "y"
(if y (reduce1 f (cons (f x y) xs))
x)))
([f start coll]
(reduce1 f (cons start coll))))
You can see that the function "f" , or the "reducing function" is called on each iteration with two arguments, the accumulated value so far, and the next value in the input sequence. The return value of this function is used as the first argument in the next call, etc. and thus has the type:
(x, y) => x
Transforming:
A transformation, the way I think you mean it, suggests the shape of the input does not change, but is simply modified according to an arbitrary function. This would be functions you pass to map, as they are applied to each element and build up a new collection of the same shape, but with that function applied to each element.
(map inc [0 1 2]) => '(1 2 3)
Notice the shape is the same, it's still a 3 element sequence, whereas in the reduction above, you input a 3 element sequence and get back an integer. Reductions can change the shape of the final result, map does not.
Note that I say the "shape" doesn't change, but the type of each element may change depending on what your "transforming" function does:
(map #(list (inc %)) [0 1 2]) => '((1) (2) (3))
It's still a 3 element sequence, but now each element is a list, not an integer.
Addendum:
There are two related concepts in Clojure, Reducers and Transducers, which I just wanted to mention since you asked about reducers (which have as specific meaning in Clojure) and transformers (which are the names Clojurists typically assign to a transducing function via the shorthand "xf"). It would turn this already long answer into a short-story if I tried to explain the details of both here, and it's been done better than I can do by others:
Transducers:
http://elbenshira.com/blog/understanding-transducers/
https://www.youtube.com/watch?v=6mTbuzafcII
Reducers and Transducers:
https://eli.thegreenplace.net/2017/reducers-transducers-and-coreasync-in-clojure/
It turns out that many transformations of collections can be expressed in terms of reduce. For instance map could be implemented as
(defn map [f coll] (reduce (fn [x y] (conj x (f y))) [] [0 1 2 3 4]))
and then you would call
(map inc [1 2 3 4 5])
to obtain
[2 3 4 5 6]
In our homemade implementation of map, the function that we pass to reduce is
(fn [x y] (conj x (f y))))
where f is the function that we would like to apply to every element. So we can write a function that produces such a function for us, passing the function that we would like to map.
(defn mapping-with-conj [f] (fn [x y] (conj x (f y))))
But we still see the presence of conj in the above function assuming we want to add elements to a collection. We can get even more flexibility by extra indirection:
(defn mapping [f] (fn [step] (fn [x y] (step x (f y)))))
Then we can use it like this:
(def increase-by-1 (mapping inc))
(reduce (increase-by-1 conj) [] [1 2 3])
The (map inc) you are referring does what our call to (mapping inc) does. Why would you want to do things this way? The answer is that it gives us a lot of flexibility to build things. For instance, instead of building up a collection, we can do
(reduce ((map inc) +) 0 [1 2 3 4 5])
Which will give us the sum of the mapped collection [2 3 4 5 6]. Or we can add extra processing steps just by simple function composition.
(reduce ((comp (filter odd?) (map inc)) conj) [] [1 2 3 4 5])
which will first remove even elements from the collection before we map. The transduce function in Clojure does essentially what the above line does, but takes care of another few extra details, too. So you would actually write
(transduce (comp (filter odd?) (map inc)) conj [] [1 2 3 4 5])
To sum up, the map function in Clojure has two arities. Calling it like (map inc [1 2 3 4 5]) will map every element of a collection so that you obtain [2 3 4 5 6]. Calling it just like (map inc) gives us a function that behaves pretty much like our mapping function in the above explanation.

Clojure - map with unbound function

I'm following a Clojure tutorial in Try Clojure, where we are introduced to defining our functions -
(defn square [x] (* x x))
Then apply it to a list of numbers:
(map square [1 2 3 4])
Which promptly prints out an error: java.lang.IllegalStateException: Attempting to call unbound fn: #'sandbox14750/square
When I try to map for example function inc, that works fine - what's the difference between the built-in function inc and my square?
I had some trouble the first time I tried to run it though after refreshing the page it went fine.
Give me some Clojure:
> (defn square [x] (* x x))
#'sandbox6361/square
> (square 4)
16
> (map square [1 2 3 4])
(1 4 9 16)
If you want to make sure your functions are still available when you need them you can store your functions in locals instead of vars like so:
> (let [square (fn [x] (* x x))] (map square [1 2 3 4]))
(1 4 9 16)
>
many sandbpxed environments like Clojurebot on #clojure don't let you define arbitrary state so it's worth knowing that functions can be stored in many ways, not just in vars.

How to map a function that adds 5 to its argument?

Please help me get off the ground with Clojure. I've searched and read, but all I see is how to add the number 1 using the function inc.
I'm trying to understand the very basics of map. All I want to do is to add the value 5 to each element in a collection. I've tried a number of different approaches, but nothing comes close. Here is one pathetic incomplete attempt:
(map (+ 5 ???) [0 1 2])
This must be childishly simple, but not for a non-functional programmer like me.
Thanks.
The first argument to map is the function you want to apply to each element in the input sequence. You could create a function and supply it:
(defn plus5 [x] (+ 5 x))
(map plus5 [0 1 2])
if you don't want to declare a named function you could create an anonymous one inline e.g.
(map (fn [x] (+ 5 x)) [0 1 2])
and you can shorten the function definition to:
(map #(+ 5 %) [0 1 2])
(+ 5 ???) is an expression, not a function.
(defn foo [x] (+ 5 x)) is a named function.
(fn [x] (+ 5 x)) is an anonymous function.
#(+ 5 %) is a faster way of writing an anonymous function.
These lines do what you want:
(map foo [0 1 2])
(map (fn [x] (+ 5 x)) [0 1 2])
(map #(+ 5 %) [0 1 2])
I find this site helpful sometimes, when looking at a language I've never seen before. If you search for "function," you'll find a whole section on how to define them. There are also six examples in the official Clojure docs for map. This is for Scala, but here's another answer on SO that explains map and reduce (left fold) pretty well.
Use partial application (see partial) to create a function that adds 5 to its argument:
(partial + 5)
You can try it yourself:
user> ((partial + 5) 10)
;; => 15
Now map it over your list:
user> (map (partial + 5) [0 1 2])
;; => [5 6 7]

In Clojure, how would I map everything to a constant value?

For example
(map #(+ 10 %1) [ 1 3 5 7 ])
Will add 10 to everything
Suppose I want to map everything to the constant 1. I have tried
(map #(1) [ 1 3 5 7 ])
But I don't understand the compiler error.
(map #(1) [ 1 3 5 7 ])
Won't work for two reasons:
#(1) is a zero-argument anonymous function, so it won't work with map (which requires a one-argument function when used with one input sequence).
Even if it had the right arity, it wouldn't work because it is trying to call the constant 1 as a function like (1) - try (#(1)) for example if you want to see this error.
Here are some alternatives that will work:
; use an anonymous function with one (ignored) argument
(map (fn [_] 1) [1 3 5 7])
; a hack with do that ignores the % argument
(map #(do % 1) [1 3 5 7])
; use a for list comprehension instead
(for [x [1 3 5 7]] 1)
; use constantly from clojure.core
(map (constantly 1) [1 3 5 7])
Of the above, I think the versions using constantly or for should be preferred - these are clearer and more idiomatic.
The anonymous function #(+ 10 %1) is equivalent to:
(fn [%1]
(+ 10 %1))
Whereas #(1) is equivalent to:
(fn []
(1))
And trying to call 1 as a function with no args just won't work.
I got this from clojure.org
by googling the words "clojure constant function" as I am just beginning to look at clojure
(map (constantly 9) [1 2 3])
cheers