The following works:
((resolve (symbol "first")) [1 2 3])
;; => 1
Why is it wrong to think that,
((read-string "first") [1 2 3])
;; => nil
should work, but it doesn't? (I get nil
.)
The return value from (resolve (symbol "first"))
is probably the Var clojure.core/first
which gets applied to the arguments.
The return value from (read-string "first")
is the symbol first
which also gets applied to the arguments. But using a symbol as a function has a different meaning. The argument is expected to be a map and the returned value is the equivalent of doing (get a-map the-symbol)
.
Any type that implements the clojure.lang.IFn
can be in the function position. The reason why using a symbol as a function with a vector argument returns nil
instead of failing, lies in the implementation details of IFn
for the Symbol
type (in this particular case for the arity 1):
public Object invoke(Object obj) {
return RT.get(obj, this);
}
RT.get()
checks if obj
implements ILookup
and calls ILookup.valAt()
if it does. Clojure vectors do implement ILookup
but they expect an integer as the provided key and return nil
for anything else.
public Object valAt(Object key, Object notFound){
if(Util.isInteger(key))
{
int i = ((Number) key).intValue();
if(i >= 0 && i < count())
return nth(i);
}
return notFound;
}
public Object valAt(Object key){
return valAt(key, null);
}