I feel curious about clojure's lazy sequence. In REPL, I defined a variable foo:
user> (def foo (map println [1 2 3]))
#'user/foo
At the first time evaluating foo, it seems to work:
user> foo
1
2
3
(nil nil nil)
But after the first time, why it becomes lazy?
user> foo
(nil nil nil)
println is not a pure function, what you're seeing in the first time you evaluate foo is the side effect of println. When you evaluate foo for the second time println is not called again, because the result of (map println [1 2 3]) is cached.
And you can see that map is lazy because when you defined foo nothing gets printed in the console. Only when evaluating foo something is printed.
Please see Laziness in Clojure.
If you use a pure function like inc:
(def foo (map inc [1 2 3]))
> foo
(2 3 4)
> foo
(2 3 4)
The result is always the same without any side effects. map, filter, etc in Clojure are designed to be used with pure functions but the language doesn't forbid you from using them with functions with side effects. In Haskell, for example you can't even write an equivalent expression, the code won't compile.
Collections hold values. The value returned by println is nil. The side-effect of println is to make something show up on your screen.
The values created by mapping println are stored in your var. This is a lazy-seq of nil values, which were returned by println.
Just to elaborate on your question.
println is only having a side effect on the *out* stream which is bound by default to the standard output.
You can have both the printing and some value returned from the function you map, e.g.
user> (defn print-and-inc [n]
(do
(println "called with n= " n)
(inc n)))
#'user/print-and-inc
do will execute each expression in sequence and return the result of the last, (inc n) in this case.
If you define now foo as a mapping of print-and-inc over a vector of int
user> (def foo (map print-and-inc [1 2 3 4 5]))
#'user/foo
user>
user> foo
called with n= 1
called with n= 2
called with n= 3
called with n= 4
called with n= 5
(2 3 4 5 6)
user>
user> foo
(2 3 4 5 6)
And you see the lazyness of map, since the printing occurs only the first time foo is called. But now foo holds the results which are the incremented values of the initial collection.
Note : this can be used to log/trace infos into your code, but there is a standard library tools.logging
In addition to what has been pointed out by others, note that experimenting with laziness within the repl is a little problematic. Lazy sequences don't actually have values until they are realised by some action that uses the value. The repl has an implicit doall to do this when printing results. This means the sequence is often realised when your using it in the repl, but may not be when using it in your real code. When you run your code, you get an unexpected result because the sequence has not been realised at a point where you expected it to be because the repl implicit doall has not been called. As an example of how this can cause moments of confusion, have a look at http://nicksellen.co.uk/2013/10/26/clojure-lazy-repl.html
Related
I've encountered a problem while I was doing a task from 4clojure.com.
Here is the description of a task:
Write a function which returns the last element in a sequence.
I've solved it using the following code:
#(first (reverse %))
When I wanted to change the first function with a number of an index.
like so:
#(0 (reverse %))
I've received an error:
java.lang.ClassCastException: java.lang.Long cannot be cast to
clojure.lang.IFn
My question is:
Why am I receiving this error?
I cannot get it, because for instance
([1 2 3 4] 0) is perfectly valid and returns the first element of a sequence so why I cannot use index of an array in the function?
EDIT1:
Even the following code does not work and I suppose APersistentVector is first there.
#((reverse %) 0)
EDIT2:
I managed to make it work by converting the list which is returned from reverse function to vector. Thanks #Josh
(#((vec (reverse %)) 0)[1 2 3])
If you look at the code for APersistentVector, you will see:
public abstract class APersistentVector extends AFn ...
AFn implements IFn, which extends java's Callable and Runnable interfaces, which means that a clojure persistent vector can be called as a function, with the argument being used as the index to retrieve. You can see this here:
public Object invoke(Object arg1) {
if(Util.isInteger(arg1))
return nth(((Number) arg1).intValue());
throw new IllegalArgumentException("Key must be integer");
}
The same is true for maps and sets; they can all be invoked as functions:
({:a 1 :b 2} :b) ;; 2
(#{:a :b} :a) ;; :a
([1 2 3 4] 0) ;; 1
However, a Long (your number zero) does not implement IFn:
(ancestors (class 42))
=>
#{java.lang.Comparable
java.lang.Number
java.lang.Object
java.io.Serializable}
Hence, it cannot be invoked as a function.
I'm trying to do a really basic problem in clojure and having some trouble wrapping my head around how vectors/lists work.
First off when I am defining the arguments of a function that has a vector as an argument, how do you represent that as an argument.
Would you just have it as a single variable say
(defn example [avector] (This is where the function goes) )
Or do you have to list each element of a vector or list beforehand?
(defn example [vectorpart1 vectorpart2 vectorpart3 vectorpart4 ] (This is where the function goes) )
Also, in terms of vectors and lists, does anyone know of commands that allow you to figure out the length of a vector or get the first/last/or nth element?
To remove the element at index n from vector v:
(defn remove-indexed [v n]
(into (subvec v 0 n) (subvec v (inc n))))
For example,
(remove-indexed (vec (range 10)) 5)
;[0 1 2 3 4 6 7 8 9]
Lots can go wrong:
v might not be a vector.
n might not be a whole number.
n might be out of range for v (we require (contains? v n).
Clojure detects all these errors at run time. A statically typed language would detect 1 and 2 but not 3 at compile time.
Your first example defines a function that takes a single argument, regardless of type. If you pass a vector then that argument will be set to a vector.
(example [1 2 3 4]) ;; (= avector [1 2 3 4])
Your second example defines a function which takes four arguments. You need to pass four separate values for calls to this function to be valid.
(example [1] [2] [3] [4])
;; (= vectorpart1 [1])
;; (= vectorpart2 [2])
;; (= vectorpart3 [3])
;; (= vectorpart4 [4])
It sounds like you might be thinking about the destructuring syntax, which allows you to destructure values directly from an argument vector.
(defn example [[a b c d]]
())
The literal vector syntax in the argument definition describes a mapping between the items in the first argument and symbols available in the function scope.
(example [1 2 3 4])
;; (= a 1)
;; (= b 2)
;; (= c 3)
;; (= d 4)
The other function that also sits in this space is apply. Apply takes a list or vector of arguments and calls a function with them in-place.
(defn example [a b c]
(assert (= a 1))
(assert (= b 2))
(assert (= c 3)))
If we call this function with one vector, you'll get an arity exception.
(example [1 2 3])
;; ArityException Wrong number of args (1) passed ...
Instead we can use apply to pass the vector as arguments.
(apply example [1 2 3])
;; no errors!
You'll find all the methods you need to work with vectors in the Clojure docs.
If you want to remove a specific element, simply take the elements before it and the elements after it, then join them together.
(def v [1 2 3])
(concat (subvec v 0 1) (subvec v 2))
The short answer is that your first example is correct. You don't want to have to name every piece of your vector because you will commonly work with vectors of indeterminate length. If you want to do something with that vector where you need its parts to be assigned, you can do so by destructuring.
The slightly longer answer is that the list of parameters sent into any clojure defn already is a vector. Notice that the parameter list uses [] to wrap its list of args. This is because in Clojure code and data are the same thing. From this article...
Lisps are homoiconic, meaning code written in the language is encoded as data structures that the language has tools to manipulate.
This might be more than you're looking for but it's an important related concept.
Here'a a quick example to get you going... Pass a vector (of strings in this case) to a functions and it returns the vector. If you map over it however, it passes the contents of the vector to the function in succession.
user=> (def params ["bar" "baz"])
#'user/params
user=> (defn foo [params] (println params))
#'user/foo
user=> (foo params)
[bar baz]
nil
user=> (map foo params)
bar
baz
(nil nil)
Additionally, look at the Clojure cheatsheet to find more about things you can do with vectors (and everything else in Clojure).
I'm using the http-kit library to make some webcalls and it returns a promise for each.
When I try to deref any of the promises in the vector I get the following error
ArityException Wrong number of args (1) passed to: core/eval5473/fn--5474 clojure.lang.AFn.throwArity (AFn.ja
va:429)
Simplest way to reproduce in a repl without http-kit is as follows
Create collection
(def x [ [1 (promise)] [2 (promise)] [3 (promise)]])
Simple Test
(map first x)
;user=> (1 2 3)
My Test
(map #(vector % #%2) x)
;user=> ArityException Wrong number of args (1) passed to: user/eval109/fn--110 clojure.lang.AFn.throwArity (AFn.java
:429)
Update
I should probably delete this question. The problem had nothing to do with promises as Valentin noted below.
I was typing %2 and thinking second argument. When what i needed was #(second %). i.e second entry in first and only argument.
The function that is the second argument of map must accept only 1 argument in this case (which is meant to be an element of the seq that is being walked through).
You seem to be mistaking passing 2 arguments to a function and passing 1 argument that is a vector of 2 elements.
What you want to write is
(map (fn [[a b]] (vector a #b)) x)
...whereas what you're currently writing is equivalent to:
(map (fn [a b] (vector a #b)) x)
So this is not a problem about promises in fact.
I understand how apply works in a simple expression like this:
(apply + '(1 2 3))
I have come across a more complex example in a book I am reading.
(def make
(fn [class & args]
(let [seeded {:__class_symbol__ (:__own_symbol__ class)}
constructor (:add-instance-values (:__instance_methods__ class))]
(apply constructor seeded args))))
In the above example, seeded is a map and args is an ArraySeq.
Can anyone explain how apply works in this context?
In this case (apply constructor seeded args) is equivalent to calling (constructor seeded arg0 arg1 arg2 ...). It unwraps the last argument (which must be seqable) and appends them one by one to the list before evaluation.
For example, this: (apply + 1 [2 3]) unrolls to (+ 1 2 3).
It seems to be analogous to:
((make) MyClass) is equivalent to new MyClass()
((make) MyClass "foo" "bar" 3) is equivalent to new MyClass("foo", "bar", 3)
The following expression in clojure works great:
(doseq [x '(1 2 3 4)] (println x))
This one gives me a nullpointer:
(doseq [x '(1 2 3 4)] ((println x)(println "x")))
It produces the following output:
user=> (doseq [x '(1 2 3 4)] ((println x)(println "x")))
1
x
java.lang.NullPointerException (NO_SOURCE_FILE:0)
user=> (.printStackTrace *e)
java.lang.NullPointerException (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:4639)
at clojure.core$eval__5182.invoke(core.clj:1966)
at clojure.main$repl__7283$read_eval_print__7295.invoke(main.clj:180)
at clojure.main$repl__7283.doInvoke(main.clj:197)
at clojure.lang.RestFn.invoke(RestFn.java:426)
at clojure.main$repl_opt__7329.invoke(main.clj:251)
at clojure.main$legacy_repl__7354.invoke(main.clj:292)
at clojure.lang.Var.invoke(Var.java:359)
at clojure.main.legacy_repl(main.java:27)
at clojure.lang.Repl.main(Repl.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at jline.ConsoleRunner.main(ConsoleRunner.java:69)
Caused by: java.lang.NullPointerException
at user$eval__266.invoke(NO_SOURCE_FILE:26)
at clojure.lang.Compiler.eval(Compiler.java:4623)
... 14 more
nil
Just adding an extra set of parentheses around the body of a doseq gives me that nullpointer.
What am I doing wrong?
Well, you already figured out the solution, so just a few hints to explain the behavior:
In Clojure (just like in Lisp, Scheme, etc) everything is an expression and an expression is either an atom or a list. With regard to lists, the Clojure manual says
Non-empty Lists are considered calls
to either special forms, macros, or
functions. A call has the form
(operator operands*).
In your example, the body ((println x) (println x)) is a list and the operator is itself an expression which Clojure has to evaluate to obtain the actual operator. That is, you're saying "evaluate the first expression and take its return value as a function to invoke upon the second expression". However, println returns, as you noticed, only nil. This leads to the NullPointerException if nil is interpreted as an operator.
Your code works with (do (println x) (println x)) because do is a special form which evaluates each expression in turn and returns the value of the last expression. Here do is the operator and the expressions with println ar the operands.
To understand the usefulness of this behavior, note that functions are first-class objects in Clojure, e.g., you could return a function as a result from another function. For instance, take the following code:
(doseq [x '(1 2 3 4)] ((if (x > 2)
(fn [x] (println (+ x 2)))
(fn [x] (println (* x 3)))) x))
Here, I am dynamically figuring out the operator to invoke upon the element in the sequence. First, the if-expression is evaluated. If x is larger than two, the if evalutes to the function that prints x + 2, else it evaluates to the function that prints x * 3. This function is than applied to the x of the sequence.
I see you've already realised the problem, however please note you don't need a do:
(doseq [x '(1 2 3 4)] (println x) (println "x"))
doseq is (as the name suggests) a do already :)