I'm reading a book on clojure, and I came by an example that I dont fully understand..
Here is the code in repl:
user=> (repeatedly 10 (rand-int 10))
ClassCastException java.lang.Integer cannot be cast to clojure.lang.IFn clojure.core/repeatedly/fn--4705 (core.clj:4642)
user=> (repeatedly 10 (partial rand-int 10))
(5 0 5 5 2 4 8 8 0 0)
My question is:
why is the partial needed here, and how does that fit into partial definition,
and repeatedly definition & syntax. Partial ...
Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args.
So how does this fit in?
Partial is just an easier way of defining an anonymous function that fixes some of the arguments to a function and then passes the rest from the arguments to the created function.
In this case
user> (repeatedly 10 (partial rand-int 10))
(3 1 3 6 1 2 7 1 5 3)
is equivalent to:
user> (repeatedly 10 #(rand-int 10))
(9 5 6 0 0 5 7 6 9 6)
Partial is a misnomer here because partial is being used to fix in advance all the arguments (or rather the only one) to rand-int.
a more intersting use of partial illustrates it's function better:
(partial + 4)
produces the equivalent of:
(fn [& unfixed-args] (apply + (concat [4] unfixed-args)))
(it does not literally produce this)
The idea being to build a function that takes the un-fixed arguments, combines them with the fixed ones, and calls the function you passed to partial with enough arguments to work properly.
user> ((fn [& unfixed-args] (apply + (concat [4] unfixed-args))) 5 6 7 8 9)
39
user> ((partial + 4) 5 6 7 8 9)
39
I only use partial in practice when the number of arguments is variable. Otherwise I have a personal preference towards using the anonymous function reader form #( ... )
partial does not actually check which arities its first argument supports; an arguably more accurate docstring would say that it "takes a function f and some arguments to f". (Clearly if you supply too many arguments, the resulting partially applied function will be broken, though that will only be observable when you try to call it.) So that's why (partial rand-int 10) is ok even though the number of arguments to rand-int supplied is not "fewer than normal".
The reason why either partial or something like #(rand-int 10) is needed here is that repeatedly expects its final argument to be a function which it can repeatedly call, whereas (rand-int 10) would be a number.
Compare this to repeat which returns a sequence with the supplied item repeated the specified number of times (or infinitely many times in the unary case). Here (rand-int 10) would be an appropriate second argument, but of course it would be some particular number, so the result would look like (8 8 8 8 8 ...); repeatedly will make a separate call to (partial rand-int 10) for each item of the sequence returned, so you'll get from it a sequence of (likely different, independent) random numbers.
repeatedly signature we are interested in: (repeatedly number function)
In this case partial will simply wrap rand-int 10 into a function that can be returned and used by the outer function, in this case repeatedly.
Without partial(or #) inner expressions are resolved before the outer ones(there are exceptions, but let's keep it simple for now), so when repeatedly is called without partial, what's gonna be passed to it is a return value of rand-int, that is Int and not a function.
Related
This question already has answers here:
How many arguments does an anonymous function expect in clojure?
(3 answers)
Closed 5 years ago.
I'm very new to Clojure and asking myself, how the arity of an anonymous function is defined/deducted.
Please consider the following poor-man count function:
(reduce #(+ 1 %1) 0 '(1 2 3 55))
Running it with clojure I'm getting the following error message:
ArityException Wrong number of args (2) passed to: user/eval1157/fn--1158 clojure.lang.AFn.throwArity (AFn.java:429)
However, it works fine with JavaScript-Clojure and returns 4 as desired (you can execute the command here).
Changing the command by exchanging %1->%2 to
(reduce #(+ 1 %2) 0 '(1 2 3 55))
would compile on both versions (but no longer work as count). In this case seemingly, it can be deduced from %2 that there are at least two arguments.
So which version of Clojure is right? Am I allowed to feed an arbitrary amount of arguments to an anonymous function defined via #(...) or only as many as mentioned inside of this function?
Should it be considered a bug in JavaScript-Clojure?
Edit: As have been explained in comments and in answer, that this is just the way how JavaScript works. There are differences to Java-Clojure, which are documented here, in particular:
There is currently no runtime enforcement of arity when calling a fn
The parameters in the resulting function is determined by the highest numbered used parameter. Thus by using %2 both become a 2 arity function, but since you only use %1 (or %) it becomes a one arity function in both versions of Clojure.
In JavaScript you can pass as many arguments as you'd like and even pass fewer than the parameter list. Variables without matching argument become undefined and arguments without defined parameters are simply not bound and available in the function. ClojureScript would have to add argument checking in each function in order to get the same behavior as in Clojure. It would be a bug if this is the specified behavior. Many transpiled languages does this.
The solution for your example is to not use the short version but rather fn:
(reduce (fn [a _] (+ 1 a)) 0 '(1 2 3 55))
As also explained in the answers of this question, Clojure determines the number of parameters of an anonymous function (defined through #()), by the maximal parameter index referenced in the body (e.g. if the maximal referenced parameter is %4, then that anonymous function has 4 parameters).
Question: is there some syntax to tell the Clojure compiler that an anonymous function expects one parameter, even not referencing that parameter? Or, in this case, the only "clean way"* is to use the fn syntax? (* "Clean way": I'm aware that in most cases, you could reference the dummy parameter without affecting the function -- see below, but I would like to avoid such workarounds.)
My use case: I have a function (defn foo [predicate]), where predicate expects exactly one argument, and I would like to test foo with a predicate that always returns true. (I.e., something like #(true).) This causes an ArityException since the interpreter thinks that #(true) expects zero arguments.
In this particular case, I could use some clever hack like #(or true %), but:
It is almost as much to type as the fn-variant.
I'm interested if there is a generic solution.
Edit: so to be clear, I'm looking for something like this:
#[1](true) ;; the anonymous function takes one parameter
No. Just use fn. That's what it's for.
If it's a constant return you are after you can use constantly:
(map (constantly 10) '(1 2 3 4 5))
; ==> (10 10 10 10 10)
If it's not you can use fn with a rest argument:
(fn [& _]
some-side-effect-expression)
; ==> non functional value
In fact this can be done on higher order functions where you don't need all the passes arguments:
(some-fun (fn [a b & _] (+ a b)) '(1 2 3 4 5))
; ==> (3 5 7 9)
If you insist on the #( ... ) syntax, you can write
#(do % true)
... incurring no run-time penalty, whatever you want to return.
But (constantly true), as #Sylvester suggests, is idiomatic, and accepts any argument list:
((constantly true) 1 2 "Buckle my shoe");true
In Clojure, there is a higher-order function reductions, which you would use with arguments similar to reduce and will return a sequence containing all intermediate results.
Is there an equivalent in Common Lisp? I was unable to find any reference to it online, including the various books/articles on https://common-lisp.net/tutorials/ but given Lisp's heritage as a family of List Processing languages I imagined a list->list function like reductions will exist across dialects.
There is no standard function for it. You could define one easily:
(defun reductions (function sequence &rest args
&key key from-end (start 0) end initial-value)
(declare (ignore key from-end start end initial-value))
"Return a list of intermediate values from reducing SEQUENCE with FUNCTION."
(let* ((reductions (list))
(result (apply #'reduce
(lambda (&rest arguments)
(let ((result (apply function arguments)))
(push result reductions)
result))
sequence
args)))
(values (or (nreverse reductions)
(list result))
result)))
(reductions #'+ '(1 2 3 4 5 6 7 8 9 10) :initial-value 0)
;=> (1 3 6 10 15 21 28 36 45 55)
Edit: Use APPLY with &REST ARGS instead of calling REDUCE directly. Some implementation of REDUCE might not work if NILs are supplied for keyword arguments.
Edit2: The reducing function can be called with 0 or 2 arguments.
Edit3: When REDUCE is called with a list of only one element, the only element is returned as is. The reducing function is not called at all, which means the list of reductions would be empty. I added an OR to return the final result wrapped in a list in that situation (to match Clojures behaviour). I also changed the code to return the final result as a second return value (might be useful and "why not?").
I am wondering that lazy-seq returns a finite list or infinite list. There is an example,
(defn integers [n]
(cons n (lazy-seq (integers (inc n)))))
when I run like
(first integers 10)
or
(take 5 (integers 10))
the results are 10 and (10 11 12 13 14)
. However, when I run
(integers 10)
the process cannot print anything and cannot continue. Is there anyone who can tell me why and the usage of laza-seq. Thank you so much!
When you say that you are running
(integers 10)
what you're really doing is something like this:
user> (integers 10)
In other words, you're evaluating that form in a REPL (read-eval-print-loop).
The "read" step will convert from the string "(integers 10)" to the list (integers 10). Pretty straightforward.
The "eval" step will look up integers in the surrounding context, see that it is bound to a function, and evaluate that function with the parameter 10:
(cons 10 (lazy-seq (integers (inc 10))))
Since a lazy-seq isn't realized until it needs to be, simply evaluating this form will result in a clojure.lang.Cons object whose first element is 10 and whose rest element is a clojure.lang.LazySeq that hasn't been realized yet.
You can verify this with a simple def (no infinite hang):
user> (def my-integers (integers 10))
;=> #'user/my-integers
In the final "print" step, Clojure basically tries to convert the result of the form it just evaluated to a string, then print that string to the console. For a finite sequence, this is easy. It just keeps taking items from the sequence until there aren't any left, converts each item to a string, separates them by spaces, sticks some parentheses on the ends, and voilà:
user> (take 5 (integers 10))
;=> (10 11 12 13 14)
But as you've defined integers, there won't be a point at which there are no items left (well, at least until you get an integer overflow, but that could be remedied by using inc' instead of just inc). So Clojure is able to read and evaluate your input just fine, but it simply cannot print all the items of an infinite result.
When you try to print an unbounded lazy sequence, it will be completely realized, unless you limit *print-length*.
The lazy-seq macro never constructs a list, finite or infinite. It constructs a clojure.lang.LazySeq object. This is a nominal sequence that wraps a function of no arguments (commonly called a thunk) that evaluates to the actual sequence when called; but it isn't called until it has to be, and that's the purpose of the mechanism: to delay evaluating the actual sequence.
So you can pass endless sequences around as evaluated LazySeq objects, provided you never realise them. Your evaluation at the REPL invokes realisation, an endless process.
It's not returning anything because your integers function creates an infinite loop.
(defn integers [n]
(do (prn n)
(cons n (lazy-seq (integers (inc n))))))
Call it with (integers 10) and you'll see it counting forever.
I am trying to really understand partial in Clojure. partial takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args. This is the working example for partial seems not making sense to me ((partial map *) [1 2 3] [4 5 6] [7 8 9]). map and * are functions; therefore partial is taking more than one function and invalidating the definition. Anyone can help me understand better?
There is nothing wrong with a function being an argument. In your case map * is created, which can be used later:
(def will-map-multiply (partial map *))
As with any partial function the rest of its arguments can be supplied later:
(will-map-multiply [1 2 3] [4 5 6] [7 8 9]) ;=> (28 80 162)
That was 'partialising' one of the arguments. It could have been two:
(def will-map-multiply-again (partial map * [1 2 3]))
(will-map-multiply-again [4 5 6] [7 8 9]) ;=> (28 80 162)
When using partial the first parameter must be a function, and the others can be whatever - no reason they can't also be functions.
Your example is a bit complex because multiplying requires two or more arguments, and hence map needs two or more sequences.
You're over-thinking it. The first argument to partial must be a function. The next arguments must be whatever would be valid arguments to that function you just named as the first argument -- including other functions, if your first parameter is a higher-order function like map or reduce or many others.
(partial map *)
The first argument is a function, map. The next argument is whatever would be a valid argument to map. Since map requires a function as its first argument, this partial expression requires a function as its second argument.
As simple as that. You can think of the * as an argument to the map first, and by extension, an argument to partial.
Functions are first-class values in Clojure. This means, you can pass them around like, for example, integers, maps or strings.
So, there’s nothing strange with (partial map *), where function * is just a map’s first argument. In your case, partial constructs a function which then passes additional collections to map. Let's see:
(partial map *)
;; becomes
(fn [coll1 coll2 coll3] ;; other arities ommited
(map * coll1 coll2 coll3))
;; let’s call this fn with your collections
((fn [coll1 coll2 coll3]
(map * coll1 coll2 coll3)) [1 2 3] [4 5 6] [7 8 9])
;; becomes
(map * coll1 coll2 coll3)
Again, the main point is that functions are first-class in Clojure and many other functional languages.
Hope this helps!
(partial map *) looks strange, but when one realizes that map takes a function as its first argument, it becomes more clear. * is just a function that takes variable number of arguments and multiplies them. Therefore,
(map * [1 2 3] [4 5 6] [7 8 9]) applies * to three triples of numbers and produces [28 80 162]. All this has nothing to do with partial. The confusion stems from the fact that in clojure functions are often passed as arguments to other functions (actually this is becoming common in all modern languages, even JavaScript!).
So, (partial map *) means exactly: take map with pre-selected first argument (*) and create a new function that uses its arguments as vectors to perform the mapping.