In a riddle I have to complete the following expressions in order to evaluate to true. There must be one single insertion, which fits to all of them.
(= 15 (reduce __ [1 2 3 4 5]))
(= 0 (reduce __ []))
(= 6 (reduce __ 1 [2 3]))
The third expression provides a start value. Hence my replacement cannot provide another one.
This function would pass the first and the third truth test:
#(+ %1 %2)
However, the second expression yields the following error:
clojure.lang.ArityException: Wrong number of args (0) passed to (...my function id)
It looks like usually reduce calls the given function only if the length of start value + collection is bigger than 2. If this length is 0, like in the case above, it is called as well - with 0 arguments.
Does anyone have a hint how to carry on here?
From the comments, the solution is clearly +, but maybe it's valuable to look at it in some detail to see why. As it turns out, there's a lot to it.
First, let's look at reduce to see what the requirements are:
(defn reduce
"f should be a function of 2 arguments. If val is not supplied,
returns the result of applying f to the first 2 items in coll, then
applying f to that result and the 3rd item, etc. If coll contains no
items, f must accept no arguments as well, and reduce returns the
result of calling f with no arguments. ..."
...
([f coll]
(if (instance? clojure.lang.IReduce coll)
(.reduce ... coll f)
...))
([f val coll]
(if (instance? clojure.lang.IReduceInit coll)
(.reduce ... coll f val)
...)))
This is a multi-arity function that either takes a function and a collection, or a function, initial value and a collection.
+ is also a multi-arity function that behaves depending on how many arguments you pass to it. The source below (edited for the parts we care about), shows reduce is satisfied by 0-arity and 2-arity.
(defn +
"Returns the sum of nums. (+) returns 0..."
...
([] 0)
...
([x y] (. clojure.lang.Numbers (add x y)))
...
Clearly (reduce + []) calls the first clause and returns 0. Test 2 is explained.
This works for the first test by applying the add function to each pair of Numbers, which happens in the Java internals for Clojure, in a tight for loop.
The final test works exactly like the first, except it calls the [v val coll] implementation of reduce. This applies a slightly different internal function, but with the same effect.
Notes
[1]: IFn is the Java interface for clojure functions
Related
A popular online tutorial gives this example to build natural numbers:
(def infseq (map inc (iterate inc 0)))
For instance, (take 5 infseq) gives:
1 2 3 4 5
I can see what (iterate inc 0) does, but, as a whole, I do not understand what exactly is going on. (For example, this is not a normal function definition.)
Could somebody please explain?
Let's break that expression down:
(map inc (iterate inc 0)))
Is a list (the datastructure) with this structure:
(function-to-call function-passed-as-first-srgument another-list-as-second-arg)
Now let's explore it by examining it from the inside out!
That inner list:
(iterate inc 0)
has this strucute
(function-to-call function-passed-as-first-argument number)
the function being called is iterate, which creates infinite sequences by keeping track of it's internal state, and every time a new value is required to make the make the sequence longer, it takes the function passed as the first argument and calls it on the current state.
the function passed as the first argument is inc which takes a numbr and ads one
the third argument to iterate is the initial-state. where it should start.
so when this inner expression is evaluated it will immediately return a data structure representing a list without actually building that list yet. When the first value is read from that list it will return the initial value 0 , when the second value is asked for it will use the inc function to come up with the number 1. If the first or second values are needed again they will just be used as is, not recalculated.
so the first argument represents a contract to produce as many numbers as are required. This is in it's self the third argument to the original expression.
The initial expression takes that lazy list and makes a new lazy list.
this new lazy list is returned by the map function.
(map inc (0 1 2 3 4 ... as many as you read ...))
which will apply inc to each of these just as it's read, and only at the moment it's read (actually it caches 20 or so items ahead to be a little faster) resulting in this sequence:
((inc 0) (inc 1) (inc 2) (inc 3) ... as much as you read from the sequence ...)
Which works out to:
(1 2 3 4 ... created lazily)
Which is the same result as these equivalent expressions,
(rest (range))
(iterate inc 1)
and many other forms.
. For the purposes of the example, we could define map and iterate as follows:
(defn iterate [f init]
(lazy-cons init (iterate f (f init))))
(defn map [f [x & xs]]
(lazy-cons (f x) (map f xs)))
... where lazy-cons is a version of cons that doesn't act until it has to. It used to be part of clojure.core, and might have been defined thus:
(defmacro lazy-cons [x xs]
`(lazy-seq (cons ~x ~xs)))
To understand these definitions, you'll need to get to grips with recursion, laziness, destructuring, and macros: quite a task! But do so and you'll really understand how clojure's sequence library, including iterate and map, works. It's how I learned.
The definition of iterate is valid. The one of map only works for a single endless sequence argument.
(take 5 (iterate inc 0)) => (0 1 2 3 4)
iterate repeatedly applys the inc function in a loop. You are starting with 0, so you get [0 1 2 3...]
(take 5 (map inc (iterate inc 0))) => (1 2 3 4 5)
(map inc <collection>) applies inc once time to each item in the collection, to the previous result is transformed to [1 2 3 4 ...]
(take 5 (range)) => (0 1 2 3 4)
range w/o any args starts at 0 and counts forever, same as the first example.
Since all of these collections are infinite in length, we need something like (take 5 <collection>) to limit the length of what is printed.
As an answer to a question on SO I was building a recurring function, and built my most complicated destructuring yet, which miraculously worked:
(defn fib?
[a b & [c & r]]
(if (= c (+ a b))
(if r
(recur b c r)
true)
false))
(fib? 0 1 1)
=> true
(fib? 2 3 5 8 13)
=> true
But I have no idea why it should work. The r used in therecur is a collection, something which would make the original function fail.
(fib? 2 3 [5 8 13])
=> false
I wanted to use something like apply recur there, but since recur is a special form, that's not possible. So I tried without it and it worked. Does recur have magical auto-apply properties or is there something else I'm not seeing.
The are two parts to the answer:
The "rest" parameter of a variadic function becomes the final parameter in any recur forms that recur to the top of the function. At this point it is no longer special in any way. You'll normally want to ensure that any values passed in that position actually are sequential, but even this is not enforced.1
Destructuring is just syntactic sugar provided by the fn and let macros. The desugared version of an fn form that uses destructuring in its parameter vector takes a certain number of regular arguments, then destructures them in a let form wrapping the entire body. Thus if you recur to the top of a function that uses destructuring in its parameter vector, the new values will be destructured for the next iteration.
1 For example, ((fn [& xs] (if (seq? xs) (recur (first xs)) xs)) 1 2 3) returns 1.
I'm trying to learn Clojure, so I figured a good way to start would be to work through the project Euler challenges with it, and the first challenge is summing all of the number below 1000 that are divisible by 3 or 5.
My original code was:
(defn div3 [input-no] (zero? (mod input-no 3)))
(defn div5 [input-no] (zero? (mod input-no 5)))
(reduce + (filter (or div3 div5) (range 1 1000)))
But that didn't work, and it turned out that the filter would just return a list of numbers divisible by 3, and not those divisible by 5.
I changed my code to:
(defn div3or5 [input-no] (or (div3 input-no) (div5 input-no)))
(reduce + (filter div3or5 (range 1 1000)))
Which got the right result, but I don't know why my original code didn't work.
Could anyone shed some light on this?
The problem you are running into is that filter expects a predicate (a function taking an input and returning true or false) as its first argument. But while div3 and div5 are functions you can't simply combine them with or. You need to construct a new function that takes one argument and feeds this to both div3 and div5 and calls or and the results of both.
Fortunately this is easy to do in Clojure, try
(filter #(or (div3 %) (div5 %)) (range1 1000))
#() is shorthand for defining a function inline (also called a lambda) and you can get to the first argument with %1 to the second with %2 and so on. If there is only one argument then you can use % for %1 see this question.
You may also want to understand that #() is just syntactic sugar for the fn form which
looks like this: (fn [arg1 arg2 ... & restArgs] (forms)). #() has some limitations (for example it can't be nested).
If you just evaluate (or div3 div5) in the REPL you can see what is happening:
=> (or div3 div5)
#<user$div3 user$div3#73305c>
That is, or is evaluating to the function div3 (which filter is then using, giving the behaviour you describe).
The reason for this is or will return its first non-falsy argument (i.e. the first argument that isn't nil or false); in this case, the arguments are two function objects and a function object is not nil or false.
To put it another way, the or is happening on the functions themselves, not the results of the functions. As Paul said, you can use an anonymous function to make or act on the results rather than the functions themselves.
I am having a problem understanding how these functions update the underlying ref, atom etc.
The docs say:
(apply f current-value-of-identity args)
(def one (atom 0))
(swap! one inc) ;; => 1
So I am wondering how it got "expanded" to the apply form. It's not mentioned what exactly 'args' in the apply form is. Is it a sequence of arguments or are these separate values?
Was it "expanded" to:
(apply inc 0) ; obviously this wouldnt work, so that leaves only one possibility
(apply inc 0 '())
(swap! one + 1 2 3) ;; #=> 7
Was it:
(apply + 1 1 2 3 '()) ;or
(apply + 1 [1 2 3])
(def two (atom []))
(swap! two conj 10 20) ;; #=> [10 20]
Was it:
(apply conj [] [10 20]) ;or
(apply conj [] 10 20 '())
The passage you quoted from swap!'s docstring means that what happens is the equivalent of swapping in a new value for the Atom obtained from the old one with (apply f old-value args), where args is a seq of all additional arguments passed to swap!.
What actually happens is different, but that's just an implementation detail. For the sake of curiosity: Atoms have a Java method called swap, which is overloaded to take from one to four arguments. The first one is always an IFn (the f passed to swap!); the second and third, in present, are the first two extra arguments to that IFn; the fourth, if present, is an ISeq of extra arguments beyond the first two. apply is never involved and the fixed arity cases don't even call the IFn's applyTo method (they just use invoke). This improves performance in the common case where not too many extra arguments are passed to swap!.
I have a sequence (foundApps) returned from a function and I want to map a function to all it's elements. For some reason, apply and count work for the sequnece but map doesn't:
(apply println foundApps)
(map println rest foundApps)
(map (fn [app] (println app)) foundApps)
(println (str "Found " (count foundApps) " apps to delete"))))
Prints:
{:description another descr, :title apptwo, :owner jim, :appstoreid 1235, :kind App, :key #<Key App(2)>} {:description another descr, :title apptwo, :owner jim, :appstoreid 1235, :kind App, :key #<Key App(4)>}
Found 2 apps to delete for id 1235
So apply seems to happily work for the sequence, but map doesn't. Where am I being stupid?
I have a simple explanation which this post is lacking. Let's imagine an abstract function F and a vector. So,
(apply F [1 2 3 4 5])
translates to
(F 1 2 3 4 5)
which means that F has to be at best case variadic.
While
(map F [1 2 3 4 5])
translates to
[(F 1) (F 2) (F 3) (F 4) (F 5)]
which means that F has to be single-variable, or at least behave this way.
There are some nuances about types, since map actually returns a lazy sequence instead of vector. But for the sake of simplicity, I hope it's pardonable.
Most likely you're being hit by map's laziness. (map produces a lazy sequence which is only realised when some code actually uses its elements. And even then the realisation happens in chunks, so that you have to walk the whole sequence to make sure it all got realised.) Try wrapping the map expression in a dorun:
(dorun (map println foundApps))
Also, since you're doing it just for the side effects, it might be cleaner to use doseq instead:
(doseq [fa foundApps]
(println fa))
Note that (map println foundApps) should work just fine at the REPL; I'm assuming you've extracted it from somewhere in your code where it's not being forced. There's no such difference with doseq which is strict (i.e. not lazy) and will walk its argument sequences for you under any circumstances. Also note that doseq returns nil as its value; it's only good for side-effects. Finally I've skipped the rest from your code; you might have meant (rest foundApps) (unless it's just a typo).
Also note that (apply println foundApps) will print all the foundApps on one line, whereas (dorun (map println foundApps)) will print each member of foundApps on its own line.
A little explanation might help. In general you use apply to splat a sequence of elements into a set of arguments to a function. So applying a function to some arguments just means passing them in as arguments to the function, in a single function call.
The map function will do what you want, create a new seq by plugging each element of the input into a function and then storing the output. It does it lazily though, so the values will only be computed when you actually iterate over the list. To force this you can use the (doall my-seq) function, but most of the time you won't need to do that.
If you need to perform an operation immediately because it has side effects, like printing or saving to a database or something, then you typically use doseq.
So to append "foo" to all of your apps (assuming they are strings):
(map (fn [app] (str app "foo")) found-apps)
or using the shorhand for an anonymous function:
(map #(str % "foo") found-apps)
Doing the same but printing immediately can be done with either of these:
(doall (map #(println %) found-apps))
(doseq [app found-apps] (println app))