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))
Related
For me as, a new Clojurian, some core functions seem rather counter-intuitive and confusing when it comes to arguments order/position, here's an example:
> (nthrest (range 10) 5)
=> (5 6 7 8 9)
> (take-last 5 (range 10))
=> (5 6 7 8 9)
Perhaps there is some rule/logic behind it that I don't see yet?
I refuse to believe that the Clojure core team made so many brilliant technical decisions and forgot about consistency in function naming/argument ordering.
Or should I just remember it as it is?
Thanks
Slightly offtopic:
rand&rand-int VS random-sample - another example where function naming seems inconsistent but that's a rather rarely used function so it's not a big deal.
There is an FAQ on Clojure.org for this question: https://clojure.org/guides/faq#arg_order
What are the rules of thumb for arg order in core functions?
Primary collection operands come first. That way one can write → and its ilk, and their position is independent of whether or not they have variable arity parameters. There is a tradition of this in OO languages and Common Lisp (slot-value, aref, elt).
One way to think about sequences is that they are read from the left, and fed from the right:
<- [1 2 3 4]
Most of the sequence functions consume and produce sequences. So one way to visualize that is as a chain:
map <- filter <- [1 2 3 4]
and one way to think about many of the seq functions is that they are parameterized in some way:
(map f) <- (filter pred) <- [1 2 3 4]
So, sequence functions take their source(s) last, and any other parameters before them, and partial allows for direct parameterization as above. There is a tradition of this in functional languages and Lisps.
Note that this is not the same as taking the primary operand last. Some sequence functions have more than one source (concat, interleave). When sequence functions are variadic, it is usually in their sources.
Adapted from comments by Rich Hickey.
Functions that work with seqs usually has the actual seq as last argument.
(map, filter, remote etc.)
Accessing and "changing" individual elements takes a collection as first element: conj, assoc, get, update
That way, you can use the (->>) macro with a collection consistenly,
as well as create transducers consistently.
Only rarely one has to resort to (as->) to change argument order. And if you have to do so, it might be an opportunity to check if your own functions follow that convention.
For some functions (especially functions that are "seq in, seq out"), the args are ordered so that one can use partial as follows:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(dotest
(let [dozen (range 12)
odds-1 (filterv odd? dozen)
filter-odd (partial filterv odd?)
odds-2 (filter-odd dozen) ]
(is= odds-1 odds-2
[1 3 5 7 9 11])))
For other functions, Clojure often follows the ordering of "biggest-first", or "most-important-first" (usually these have the same result). Thus, we see examples like:
(get <map> <key>)
(get <map> <key> <default-val>)
This also shows that any optional values must, by definition, be last (in order to use "rest" args). This is common in most languages (e.g. Java).
For the record, I really dislike using partial functions, since they have user-defined names (at best) or are used inline (more common). Consider this code:
(let [dozen (range 12)
odds (filterv odd? dozen)
evens-1 (mapv (partial + 1) odds)
evens-2 (mapv #(+ 1 %) odds)
add-1 (fn [arg] (+ 1 arg))
evens-3 (mapv add-1 odds)]
(is= evens-1 evens-2 evens-3
[2 4 6 8 10 12]))
Also
I personally find it really annoying trying to parse out code using partial as with evens-1, especially for the case of user-defined functions, or even standard functions that are not as simple as +.
This is especially so if the partial is used with 2 or more args.
For the 1-arg case, the function literal seen for evens-2 is much more readable to me.
If 2 or more args are present, please make a named function (either local, as shown for evens-3), or a regular (defn some-fn ...) global function.
I've been into Clojure lately and have avoided macros up until now, so this is my first exposure to them. I've been reading "Mastering Clojure Macros", and on Chapter 3, page 28, I encountered the following example:
user=> (defmacro square [x] `(* ~x ~x))
;=> #'user/square
user=> (map (fn [n] (square n)) (range 10))
;=> (0 1 4 9 16 25 36 49 64 81)
The context is the author is explaining that while simply passing the square macro to map results in an error (can't take value of a macro), wrapping it in a function works because:
when the anonymous function (fn [n] (square n)) gets compiled, the
square expression gets macroexpanded, to (fn [n] (clojure.core/* n
n)). And this is a perfectly reasonable function, so we don’t have any
problems with the compiler
This makes sense to me if we assume the body of the function is evaluated before runtime (at compile, or "definition" time) thus expanding the macro ahead of runtime. However, I always thought that function bodys were not evaluated until runtime, and at compile time you would basically just have a function object with some knowledge of it's lexical scope (but no knowledge of its body).
I'm clearly mixed up on the compile/runtime semantics here, but when I look at this sample I keep thinking that square won't be expanded until map forces it's call, since it's in the body of the anonymous function, which I thought would be unevaluated until runtime. I know my thinking is wrong, because if that was the case, then n would be bound to each number in (range 10), and there wouldn't be an issue.
I know it's a pretty basic question, but macros are proving to be pretty tricky for me to fully wrap my head around at first exposure!
Generally speaking function bodies aren't evaluated at compile time, but macros are always evaluated at compile time because they're always expanded at compile time whether inside a function or not.
You can write a macro that expands to a function, but you still can't refer/pass the macro around as if it were a function:
(defmacro inc-macro [] `(fn [x#] (inc x#)))
=> #'user/inc-macro
(map (inc-macro) [1 2 3])
=> (2 3 4)
defmacro is expanded at compile time, so you can think of it as a function executed during compilation. This will replace every occurrence of the macro "call" with the code it "returns".
You may consider a macros as a syntax rule. For example, in Scheme, a macros is declared with define-syntax form. There is a special step in compiler that substitutes all the macros calls into their content before compiling the code. As a result, there won't be any square calls in your final code. Say, if you wrote something like
(def value (square 3))
the final version after expansion would be
(def value (clojure.core/* 3 3))
There is a special way to check what will be the body of your macros after being expanded:
user=> (defmacro square [x] `(* ~x ~x))
#'user/square
user=> (macroexpand '(square 3))
(clojure.core/* 3 3)
That's why a macros is an ephemeral thing that lives only in source code but not in the compiled version of it. That's why it cannot be passed as a value or referenced somehow.
The best rule regarding macroses is: try to avoid them until you really need them in your work.
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
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.
I'm trying to use the longs function, but it's not working:
(println (longs 1 2 3))
Any examples?
The description in the site is not very good, which is why I'm having problems
http://clojure.org/cheatsheet
Thanks
You're question is woefully incomplete, but I'll take a stab at it anyway.
The documentation for longs says:
Usage: (longs xs)
That means, it's expecting one argument (named xs in this example). You're passing it three arguments.
The documentation for longs continues thus:
Casts to long[]
Casting means: It doesn't change xs, it simply checks that it is an array of primitive long and then make this information available to the compiler. Basically, wrapping an expression that produces a long[] in (longs ...) is a type hint for Clojure so that it doesn't have to use reflection at runtime to resolve a method call using that value as an argument:
// Suppose we have a java class
class JavaClass {
static long[] getSomeLongs() { ... }
static long sum(long[] numbers) { ... }
static float sum(float[] numbers) { ... }
}
;; And this Clojure code:
(defn numbers [] (JavaClass/getSomeLongs))
(JavaClass/sum (numbers))
Clojure is dynamically typed, so when it compiles the second line, it won't know that (numbers) returns an array of long. It will have to wait until run time and then look up the correct JavaClass/sum method using reflection. This is expensive.
The solution is to give the Clojure compiler a hint about the type of (numbers). That way it can choose the correct method to call at compile time, resulting in a faster running program:
(JavaClass/sum (longs (numbers)))
But, judging from your woefully incomplete question, that's probably not what you were expecting when you reached for longs. It seems you were hoping it would create an array of longs from the arguments you gave it. If that's what you want then use this:
(into-array Long/TYPE [1 2 3])
But, you're likely to be disappointed by the results of printing it:
user=> (println (into-array Long/TYPE [1 2 3]))
#<long[] [J#2321b59a>
That's what Java gives back when you ask it to convert an array into a String, so that's what Clojure prints. If you want to see the contents of the array printed back, you need to make a sequence:
user=> (println (seq (into-array Long/TYPE [1 2 3])))
(1 2 3)