clojure: Wrong number of args (0) passed to clojure.lang.PersistentArrayMap - clojure

Following along with this comment, I'm using clojure.core.memoize to memoize results of some db calls:
(def get-user-profile-cached
(memo/memo (get-user-profile)))
get-user-profile returns a map.
I try to use the cached get in a let within a function:
(defn get-user-from-token [token]
(let [user (get-user-profile-cached)
id (:id user)]
...))
This let statement causes the following error: clojure.lang.ArityException: Wrong number of args (0) passed to: clojure.lang.PersistentArrayMap.
What am I doing wrong?

By using (get-user-profile), you're already calling the function and making memo cache its result, the map.
Try passing get-user-profile instead, without the parentheses.

Related

appending values in a global map in clojure

I declared a map in clojure using
(def finalMap {})
I am appending values to it inside a function using assoc but they are not appending, the map is remaining empty. I think it is due to immutability, can I in some way make a global map mutable.The function is a recursive one and I am appending values each time the function is called.
(defn func [arg1 arg2]
;(map append inside let)
(dorun (for [i (range 0 index)]
(do
(func(arg1 arg2))))))
Can you help me with the correct way to do this?
If you want a mutable map then you should create an atom:
(def final-map (atom {}))
Also normally you would use assoc to add more key value pairs to it. However you will need to use swap! just to be able to call assoc:
(swap! final-map assoc :a "a value")
This will add a key/value pair where the key is the keyword :a and the value is the String "a value".
It might be good to view some other examples of using assoc. Realise that in the code above assoc is being called with the old value of final-map as its first argument, and returning the new value of final-map.

clojure function behaves like a symbol when called without argument

I get the following weird behaviour from a clojure function: When I call it with one argument it seems as if it is a function, when I call it without arguments it appears to be a symbol. Any ideas how this can be?
this is what happens in the interpreter:
=> (input-updatef -1)
ArityException Wrong number of args (1) passed to: modelingutils/create-process-level/input-updatef--2954 clojure.lang.AFn.throwArity (AFn.java:429)
and when I try calling it without any argument:
=> (input-updatef)
ArityException Wrong number of args (0) passed to: Symbol clojure.lang.AFn.throwArity (AFn.java:429)
Thx!
Answering "how this can be":
user=> (defn foo [] ('foo))
#'user/foo
user=> (foo 1)
ArityException Wrong number of args (1) passed to: user/foo clojure.lang.AFn.throwArity (AFn.java:429)
user=> (foo)
ArityException Wrong number of args (0) passed to: Symbol clojure.lang.AFn.throwArity (AFn.java:429)
Of course your input-updatef situation may be more subtle, but it is at least clear that
either the actual input-updatef function has no unary overload or it has one, but when you call it it ends up calling a function that has no unary overload with just one argument;
it has a nullary overload;
calling the nullary overload results in a call to a symbol with no arguments.
Also, based on the modelingutils/create-process-level/input-updatef--2954 part of your error message it seems to me that input-updatef might be a "local function" – created using letfn or introduced as the value of a let binding – returned at some point from a function called create-process-level. Here's an example of what that could look like:
user=> (defn foo
([]
('foo))
([x]
(letfn [(f [])]
(f x))))
#'user/foo
user=> (foo 1)
ArityException Wrong number of args (1) passed to: user/foo/f--4 clojure.lang.AFn.throwArity (AFn.java:429)
user=> (foo)
ArityException Wrong number of args (0) passed to: Symbol clojure.lang.AFn.throwArity (AFn.java:429)
Using
(defn foo
([]
('foo))
([x]
(let [f (fn [])]
(f x))))
would have the same effect.
Thanks, both answers helped.
I did not post the definition, because it contained a complex macro..
The problem was that I called the macro from a normal function and supplied an argument (an ff function) to this macro from the argument list of the calling function. This ff was interpreted as a symbol at macro evaluation time -- this is what caused the strange behaviour.
Solution: I changed the outer calling function into a macro, and unquoted ff in the argument list of the called macro.

Wrong number of arguments for a simple function

Can someone explain the behavior in the Clojure code below?
I don't get it.
Does Clojure somehow replace or "optimize" function arguments? Why does calling a function with a single nil argument result in an ArityException?
(defn foo [bar] (reduce #(%1) bar))
(foo nil)
-> ArityException Wrong number of args (0) passed to: test$foo$fn clojure.lang.AFn.throwArity (AFn.java:437)
See (doc reduce):
[...]
If coll contains no
items, f must accept no arguments as well, and reduce returns the
result of calling f with no arguments.
[...]
Here coll is nil, which is effectively being treated as a collection containing no items (as it usually is in similar contexts), and f is #(%1).
Thus #(%1) is being called with no arguments and ends up throwing the exception you see.

clojure instance? single argument

I am a little confused by the clojure instance? function. It seems quite happy to take a single argument. So
(instance? String)
works fine, but always returns false.
Am I missing something here? I've done this twice in two days, and both times it took me a quite a long time to debug (yes, I agree, to make the mistake once might be regarded as misfortune, but twice looks like carelessness).
Why doesn't it break, with an arity error?
Note added later:
As of Clojure 1.6 this has been fixed!
http://dev.clojure.org/jira/browse/CLJ-1171
Interesting... even though instance? is defined in core.clj, it appears that there is special handling built in to clojure.lang.Compiler for (instance?) forms.
Compiler.java, line 3498:
if(fexpr instanceof VarExpr && ((VarExpr)fexpr).var.equals(INSTANCE))
{
if(RT.second(form) instanceof Symbol)
{
Class c = HostExpr.maybeClass(RT.second(form),false);
if(c != null)
return new InstanceOfExpr(c, analyze(context, RT.third(form)));
}
}
I interpret that to mean that, when you compile/evaluate an (instance?) form, the function defined in core.clj is ignored in favor of the hard-wired behavior, which does interpret a missing second argument as nil. I'm guessing this is done for performance reasons, as a sort of in-lining.
Apparently this special handling only applies in certain cases (and I'm not familiar enough with the compiler to know what they are). As illustrated by Ankur's answer, there are ways of calling instance? that cause the function defined in core.clj to be invoked.
I think it is a bug. If you define a new version of instance?, e.g.
(def
^{:arglists '([^Class c x])
:doc "Evaluates x and tests if it is an instance of the class
c. Returns true or false"
:added "1.0"}
foo? (fn foo? [^Class c x] (. c (isInstance x))))
you will get the expected exception
user=> (foo? String "bar")
true
user=> (foo? String 1)
false
user=> (foo? String)
ArityException Wrong number of args (1) passed to: user$foo-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)
If you look at the instance? code you will see that the method isInstance of Class is called:
(def
^{:arglists '([^Class c x])
:doc "Evaluates x and tests if it is an instance of the class
c. Returns true or false"
:added "1.0"}
instance? (fn instance? [^Class c x] (. c (isInstance x))))
Looks like under the hood, nil (or false) is considered as the default value for x parameter when passed to the isInstance and that returns false.
Hmm....interesting... all the below calls fails (which is how it is supposed to be):
user=> (.invoke instance? String)
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)
user=> (instance? (type ""))
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)
user=> (apply instance? String [])
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)
user=> (#'instance? Long)
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)
Event creating a new instance of "instance?" function object works as it is supposed to work:
user=> (def a (.newInstance (aget (.getConstructors (type instance?)) 0) (into-array [])))
#'user/a
user=> (a String)
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437)
user=> (a String "")
true

In Clojure how to choose a value if nil

In Clojure what is the idiomatic way to test for nil and if something is nil then to substitute a value?
For example I do this a lot:
let [ val (if input-argument input-argument "use default argument")]
: but I find it repetitive having to use "input-argument" twice.
just use or:
(or input-argument "default")
Alex's suggestion of "or" is indeed the idiomatic way to rewrite your example code, but note that it will not only replace nil values, but also those which are false.
If you want to keep the value false but discard nil, you need:
(let [val (if (nil? input-argument) "use default argument" input-argument)]
...)
If you only bind the variable to do get the right value and not to use it twice there is a other way you can do it. There is a function in core called fnil.
You call fnil with the function you want to call and the default argument. This will return a function that will replace nils with the default value you provided.
The you can do one of the things depending on what you want. Creat a local function.
(let [default-fn (fnil fn-you-want-to call "default-argument")]
(default-fn input-argument))
In somecases (where you always have the same default argument) you can move to logic to do this out of your code and put it where to original function was (or wrap the function in case it in a other library).
(defn fn-you-want-to-call [arg] ....)
(def fn-you-want-to-call-default (fnil fn-you-want-to-call "default-argument"))
Then in your code its reduced to just
(fn-you-want-to-call-default input-argument)
More you can find here:
http://clojuredocs.org/clojure_core/clojure.core/fnil
When the expected value is a boolean I recommend using an util fn.
(defn- if-nil [default val]
(if (nil? val)
default
val))
(if-nil true (possible-false input))