I'm new to clojure. What is the difference between (3) and just 3? If I do (3) I get this exception:
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn.
3 is literal number 3.
(3) is a a function application, you are trying to call function 3 with no parameters. (There's no such function and it seems you can't define it.)
'(3) is a list of one item, 3. It's the same as (list 3), which is a function application.
Here is a repl session:
repl=> 3
3
repl=> (3)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn repl/eval1388 (NO_SOURCE_FILE:1)
repl=> '(3)
(3)
repl=> (list 3)
(3)
repl=> => (defn 3 [] 3)
ClassCastException java.lang.Long cannot be cast to clojure.lang.IObj clojure.core/with-meta (core.clj:211)
In lisps parenthesis mean function application, so this:
(a b c d)
means apply a to arguments b c d
You're trying to apply 3, which is not a function, nor can it be converted to one.
In Clojure, parentheses mean function application. (3) is trying to call a function named 3, which doesn't exist.
When you start with a Lisp you have to get used to the fact that parenthesis are significative. You can't just add more parenthesis in hope to disambiguate operator priorities – however since everything is in prefix form there's no operator ambiguity.
Once you get used to the fact that all parenethesis matter, try to mentally move the opening one one item to the right, e.g. (println "hello")becomes println("hello").
Since the language is very regular it implies that (3) should be read as 3(). 3 is not a function thus you can't call it.
Related
In clojure, we can use unquote slicing ~# to spread the list. For example
(macroexpand `(+ ~#'(1 2 3)))
expands to
(clojure.core/+ 1 2 3)
This is useful feature in macros when rearranging the syntax. But is it possible to use unquote slicing or familiar technique outside of macro and without eval?
Here is the solution with eval
(eval `(+ ~#'(1 2 3))) ;-> 6
But I would rather do
(+ ~#'(1 2 3))
Which unfortunately throws an error
IllegalStateException Attempting to call unbound fn: #'clojure.core/unquote-splicing clojure.lang.Var$Unbound.throwArity (Var.java:43)
At first I thought apply would do it, and it is indeed the case with functions
(apply + '(1 2 3)) ; -> 6
However, this is not the case with macros or special forms. It's obvious with macros, as it's expanded before apply and must be first element in the form anyway. With special forms it's not so obvious though, but still makes sense as they aren't first class citizens as functions are. For example the following throws an error
(apply do ['(println "hello") '(println "world")]) ;-> error
Is the only way to "apply" list to special form at runtime to use unquote slicing and eval?
Clojure has a simple model of how programs are loaded and executed. Slightly simplified, it goes something like this:
some source code is read from a text stream by the reader;
this is passed to the compiler one form at a time;
the compiler expands any macros it encounters;
for non-macros, the compiler applies various simple evaluation rules (special rules for special forms, literals evaluate to themselves, function calls are compiled as such etc.);
the compiled code is evaluated and possibly changes the compilation environment used by the following forms.
Syntax quote is a reader feature. It is replaced at read time by code that emits list structure:
;; note the ' at the start
user=> '`(+ ~#'(1 2 3))
(clojure.core/seq
(clojure.core/concat (clojure.core/list (quote clojure.core/+)) (quote (1 2 3))))
It is only in the context of syntax-quoted blocks that the reader affords ~ and ~# this special handling, and syntax-quoted blocks always produce forms that may call a handful of seq-building functions from clojure.core and are otherwise composed from quoted data.
This all happens as part of step 1 from the list above. So for syntax-quote to be useful as an apply-like mechanism, you'd need it to produce code in the right shape at that point in the process that would then look like the desired "apply result" in subsequent steps. As explained above, syntax-quote always produces code that creates list structure, and in particular it never returns unquoted expressions that look like unquoted dos or ifs etc., so that's impossible.
This isn't a problem, since the code transformations that are reasonable given the above execution model can be implemented using macros.
Incidentally, the macroexpand call is actually superfluous in your example, as the syntax-quoted form already is the same as its macroexpansion (as it should be, since + is not a macro):
user=> `(+ ~#'(1 2 3))
(clojure.core/+ 1 2 3)
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 closure, if you run the following code :
(conj (1 2 3) 4)
It'll error and say :
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
However, if you place an apostrophe before the list, it'll run fine
(conj '(1 2 3) 4)
My question is, what exactly does this apostrophe do, and why is it actually necessary for this list?
I've noted that this doesn't happen when you use a vector
(conj [1 2 3] 4)
In fact, even if you use an apostrophe (conj '[1 2 3] ), it'll still work fine and return the same result.
What exactly does the apostrophe do, and why does a list require it, but a vector does not? (Apologies if this is a beginner/stupid question, I'm still learning. A thorough answer would be greatly appreciated)
There is a fundamental difference betweeen list (the parentheses) and vector (the brackets), that lists are used for function calls, and vectors are simply vector literals.
An apostrophe is a reader macro for the quote, that suppresses evaluation. E.g., (+ 1 2) is evaluated to a 3 when read in from source file, but '(+ 1 2) is read in as a list, or clojure.lang.PersistentList, conforming to the idea of code is data in lisp. On the other hand, quoting a vector is simply the vector itself.
So in your case, (conj (1 2 3) 4) when read in, it will try to call a function named 1 with arguments 2 and 3, no wonder it fails. But a quoted list, or a vector can be appended with an extra element.
OK, a fibonacci function in Clojure:
(defn give-fibs []
((fn fib-seq [a b]
(cons a (lazy-seq (fib-seq b (+ a b)))))
0 1))
Now, my question is, when I call it like so, I get an error :
(take 10 give-fibs)
edit, error is - java.lang.IllegalArgumentException: Don't know how to create ISeq from: four_cloj.core$give_fibs
However, it works when I call:
(take 10 (give-fibs))
When I check out what's going on, I can't really explain it:
(class (give-fibs)) ; clojure.lang.Cons
(class give-fibs) ; four_cloj.core$give_fibs
??
give-fibs is just that - the function itself. The concept of a function as a value that can be passed around (for example, as argument to take) takes some getting used to, but it's perfectly sensible and normal.
(give-fibs) is the result of calling give-fibs with no arguments, which is what you want in this context. The result is a list, and each element of a list is a Cons object, which is what class tells you.
In this expression you don't really call give-fibs:
(take 10 give-fibs)
you just pass the function itself to take. What you want is to actually call give-fibs in order to pass result of it to take:
(take 10 (give-fibs))
Remember that the first element in an s-expression is considered to be in function position, that is to say it will be executed. Therefore give-fibs and (give-fibs) are different in that the former is the actual function being passed to take and the latter is calling that function, and therefore returning the result to be passed to take.
Thats why (class give-fibs) is a function, and (class (give-fibs)) is a Cons cell as expected.
Just remember the first var after an opening bracket is in function position and will be executed, and its perfectly valid to pass an unexecuted function to another.
I understand that Lisps are (usually) dynamically typed, but I guess their values still have types. Functions are values in lisps, so I wonder what is the type of function +?
List of numbers -> number seemed most likely, so I tried (+ '(2 3)) and (+ [2 3]) in Clojure, but neither worked.
Is it possible to query the type of a value (or expression) in Clojure REPL?
It's actually quite a complex type that is tricky to define formally for a number of reasons:
It's a multi-arity function (accepts an variable number of parameters). Note that this is different from a function that takes a single parameter which is a list of numbers. If you want to use + on a list of numbers you need to use apply e.g. (apply + [1 2 3 4])
Each parameter can be a Number of any type. There are many possible number types, indeed anything that extends the java.lang.Number base class would suffice.
Inlined versions are defined which can directly produce primitive types as a result.
There isn't an easy way to determine this from the REPL. But you might be interested in Typed Clojure which provides a type system along with methods to define types and do corresponding type checking in Clojure. It uses a neat approach called "gradual typing", so you can add type annotations just where you need them: you don't need to assign types to the whole program at once.
Clojure has the type function.
> (type +)
clojure.core$_PLUS_
> (type clojure.core$_PLUS_)
java.lang.Class
> (type (+ 1 1))
java.lang.Long
> (type (+ 1.0 1.0))
java.lang.Double
So the + function returns either a Long or a Double depending on the arguments.
The other arithmetic functions also return different types depending on the arguments:
> (type (/ 3 1))
java.lang.Long
> (type (/ 3.0 1))
java.lang.Double
> (type (/ 1 3))
clojure.lang.Ratio
If you want to see how the function is implemented, it's as simple as visiting the source. This lets you see how to define multi-arity functions.