Clojure. Vectors and Lists. cons and peek - clojure

Clojure noob here. Playing around with lists and vectors.
> (peek [1 2 3 4])
4
> (peek '(1 2 3 4))
1
Works as promised. Just like this does.
> (cons 1 [2 3 4])
(1 2 3 4)
> (cons 1 '(2 3 4))
(1 2 3 4)
I randomly tried to use peek on the result of cons:
> (peek (cons 1 [2 3 4]))
ClassCastException clojure.lang.Cons cannot be cast to clojure.lang.IPersistentStack clojure.lang.RT.peek (RT.java:724)
What is going on?

Playing around I found that cons doesn't plainly return a sequence like it claims. My guess is that it returns a lazy sequence because:
> (type (cons 1 [2 3 4]))
clojure.lang.Cons
I found this way of realizing it
> (peek (into [] (cons 1 '(2 3 4))))
4

Concerning your answer:
Playing around I found that cons doesn't plainly return a sequence
like it claims.
Yes it does: cons always returns a sequence:
cons returns a clojure.lang.Cons,
which extends ASeq,
which implements ISeq.
My guess is that it returns a lazy sequence ...
A Cons is never a lazy sequence. It may be wrapped in a lazy sequence. Its tail may be a lazy sequence. But it, itself, is not a lazy sequence.
Concerning your question:
peek doesn't work on cons because peek requires an IPersistentStack: an interface that Cons doesn't implement. So far as I can see, it well could.

Related

Clojure: how to convert cons to list

(cons 1 (list 2 3)) returns a clojure.lang.cons. How can I convert it to clojure.lang.PersistentList?
Instead of calling cons and trying to convert the result, use conj:
(conj (list 2 3) 1)
=> (1 2 3)
(type (conj (list 2 3) 1))
=> clojure.lang.PersistentList
Clojure: how to convert cons to list
Don't!
Clojure is built upon extensible abstractions. One of the most important is the sequence.
I can think of no reason why you would want to convert a cons into a listor vice versa. They are both sequences and nothing much else. What you can do with one you can do with the other.
The above takes forward Leetwinski's comment on the question.
You can apply the contents of the returned sequence to the list function:
(apply list (cons 1 (list 2 3)))
=> (1 2 3)
(type *1)
=> clojure.lang.PersistentList
The easiest way would be to turn it into a vector. This data type works great in Clojure. In fact, when programming in Clojure, the most of the data is kept either in vectors or maps while lists are used for "code as data" (macro system).
In your case, the solution would be:
user=> (vec (cons 1 (list 2 3)))
[1 2 3]
I don't know such a case where you need a list exactly, not a vector or a seq. Because most of the functions operate on sequences but not strict collection types. The cons type should also work, I believe.
If you really need a list, you may use into function that is to convert collections' types. But please keep in mind that when dealing with a list, the order will be opposite:
user=> (into '() (cons 1 (list 2 3)))
(3 2 1)
So you need to reverse the input data first:
user=> (into '() (reverse (cons 1 (list 2 3))))
(1 2 3)
user=> (type (into '() (reverse (cons 1 (list 2 3)))))
clojure.lang.PersistentList

(clojure.core/seq) instead of list

I am not understand why instead of normal list I recive (clojure.core/seq).
My code
(defn del-list [arg-list lvl] (do
(cond
(= lvl 1) (remove seq? arg-list)
:else (map #(if (seq? %)
(del-list % (- lvl 1))
%
) arg-list)
)
))
(println (del-list `(1 2 3 `(1 2 `(1 2 3) 3) 1 2 3) 2))
;result=> (1 2 3 (clojure.core/seq) 1 2 3)
Why is this happening? I don't know how valid search this, all links from google point me to documentation about seq and seq?.
Like #ClojureMostly says in the comments, don't use bacticks, use a single quote. Also don't nest them, one is enough.
So, calling your function like this:
(println (del-list '(1 2 3 (1 2 (1 2 3) 3) 1 2 3) 2))
Will solve your immediate problem.
Going into a bit more depth, there are some differencences between single quote (just called quote) and backtick (called syntax quote).
In quoting something, you say that you want just the data structure, that it shouldn't be evaluated as code. In clojure, code is data, so (+ 1 2) is a list with a symbol and two numbers which, when evaluated as code, evals to 3. So, (+ 1 2) => 3 and '(+ 1 2) => (+ 1 2).
Syntax quote is similar, but it looks up the namespaces of things and you can unquote stuff inside. This makes it useful for writing macros.
;; Looks up the namespaces of symbols to avoid the problem of variable capture
`(+ 1 2) ;=> (clojure.core/+ 1 2)
;; You can unquote parts of the expression.
;; ~ is unquote ~# is unqoute splicing
;; That should give you the vocabulary to google this.
`(+ 1 2 3 ~(* 2 2)) ;=> (clojure.core/+ 1 2 3 4)
Nested quotes are never what you want. (Unless you alternate quoting and unquoting, and even then it's usually confusing)
In clojure you'd usually represent sequential things as vectors [1 2 3] (O(n) random access, grows at the end), unless you specifically want some property of a linked list for your data. (Like representing a stack, as lists efficiently add and remove the first element.)
(defn del-list [arg-list lvl]
;; You don't need the do, there's an implicit do in many special forms
;; like let, fn and defn
;; Also you only had one thing in your do, in that case it doesn't do anything
;; There's only one condition, so I'd use if instead of cond
(if (= lvl 1)
;; And, like someone mentioned in the comments,
;; what you probably want is sequential? instead of seq?
(remove sequential? arg-list)
(map #(if (sequential? %)
(del-list % (dec lvl)) ; dec stands for decrement
%)
arg-list)))
;; This works
(println (del-list '(1 2 3 (1 2 (1 2 3) 3) 1 2 3) 2))
;; But this is more idiomatic (modulo specific reasons to prefer lists)
(println (del-list [1 2 3 [1 2 [1 2 3] 3] 1 2 3] 2))
;; If you change map to mapv, and wrap remove with vec it will return vectors
(defn del-vec [arg-vec lvl]
(if (= lvl 1)
(vec (remove sequential? arg-vec))
(mapv #(if (sequential? %)
(del-vec % (dec lvl)) ; dec stands for decrement
%)
arg-vec)))
(println (del-vec [1 2 3 [1 2 [1 2 3] 3] 1 2 3] 2))
;; But most of the time you don't care about the specific type of sequential things
As for your actual question, why does clojure.core/seq appear, I have no idea. That's not how you use quoting, so it has never come up.

How does this Clojure form work? Removing a list from another list

I am doing a project for class and I stumbled upon some code that has proved useful, though I am not sure how the line below "reads". I understand the result of what it does, but not how it does it.
(remove #(some (partial = %) '(1 2 3 4)) '(1 2 3 5 6 7))
What it does is removes the values from the second set that are in the first if possible. So given two set P and V it finds P / V.
I guess I am looking for an English language sentence of what is happening?
Edit: Title. Also I do understand what remove does, given some predicate such as pos? it returns a lazy sequence of items that equate to true when the predicate is applied.
What I specifically do not understand is how #(some (partial = %)) evaluates to a predicate.
#(some (partial = %) '(1 2 3 4))
...is syntax sugar for...
(fn [x] (some (partial = x) '(1 2 3 4))
...so, calling
(#(some (partial = %) '(1 2 3 4)) 5)
...runs...
(some (partial = 5) '(1 2 3 4))
...thus, running (partial = 5) against every entry in '(1 2 3 4) until it finds a match -- thus: (= 5 1), (= 5 2), etc -- and returning nil when no match is returned.
nil is falsey. Thus, any sequence element for which no match exists will return false, and be retained by remove, whereas for anything with which a match exists, the predicate will return true and be removed.
Obviously, creating a lambda function for every item in one of your sequences and evaluating those functions against content of another sequence is extremely inefficient compared to real set arithmetic. Thus, this code shouldn't be used in any case where the number of items might be nontrivial.
Instead:
(clojure.set/difference
#{1 2 3 4 5 6 7}
#{1 2 3 4})
...would be the efficient and idiomatic approach. If you're starting with a list rather than a set literal, that might be replaced with (clojure.set/difference (into #{} list-a) (into #{} list-b)) or (clojure.set/difference (set list-a) (set list-b)).

How to apply a function to a sequence multiple times

I am working on some Lisp exercises using Clojure. I am trying to work these exercises without taking advantage of vectors and some Clojure functions.
This function
(defn rev-seq
[s1]
(concat (pop s1) (list (peek s1))))
puts the first element of a list at the end. I want to call this function as many times as it takes to reverse the list (without calling Clojure's reverse function).
I am not sure what to use in its place. I have experimented with map, apply, and repeat with no success. I would rather have a way to think differently about this than a straight answer, but I am not asking for a discussion.
Firstly, I think you'll need to convert rev-seq to use first/rest rather than peek/pop if you want to work on general sequences - at leas in Clojure 1.4 peek/pop seems to require a PersistentStack:
(defn rev-seq
[s1]
(concat (rest s1) (list (first s1))))
Then you should probably note that applying this function repeatedly will "cycle" a list rather than reversing it. You can see that if you look at the result of a small number of applications using iterate:
(def s '(1 2 3 4 5 6 7 8 9))
(nth (iterate rev-seq s) 3)
=> (4 5 6 7 8 9 1 2 3)
An option that would work is to reverse with a recursive function:
(defn reverse-seq [s]
(concat (reverse (next s)) (list (first s))))
(reverse-seq s)
=> (9 8 7 6 5 4 3 2 1)
Or alternatively you can do a reverse using the technique in clojure.core:
(defn reverse-seq [s]
(reduce conj () s))
(reverse-seq s)
=> (9 8 7 6 5 4 3 2 1)
Hope this gives you some ideas!
Recursion is powerful!
I translated
the solution
into Clojure.
(defn- inverte-aux
[lista resto]
(if lista
(recur (next lista) (cons (first lista) resto))
resto))
(defn inverte
[lista]
(inverte-aux lista nil))
user> (inverte [4 3 2 1 3])
(3 1 2 3 4)

In Lisp (Clojure, Emacs Lisp), what is the difference between list and quote?

From reading introductory material on Lisp, I now consider the following to be identical:
(list 1 2 3)
'(1 2 3)
However, judging from problems I face when using the quoted form in both Clojure and Emacs Lisp, they are not the same. Can you tell me what the difference is?
The primary difference is that quote prevents evaluation of the elements, whereas list
does not:
user=> '(1 2 (+ 1 2))
(1 2 (+ 1 2))
user=> (list 1 2 (+ 1 2))
(1 2 3)
For this reason (among others), it is idiomatic clojure to use a vector when describing a literal collection:
user=> [1 2 (+ 1 2)]
[1 2 3]
In Common Lisp, quoted objects are constant literal data. The data is not evaluated. You should not modify this data, as the consequences are undefined. Possible consequences are: modification of shared data, attempt to modify read-only data, an error might be signalled, it might just work, shared data, ...
Literal lists:
'(1 2 3)
Above is a constant list, which will be constructed by the reader and evaluating to itself, because it is quoted. If it appears in Lisp code, a compiler will embed this data somehow in the FASL code.
(quote (1 2 3)) is another way to write it.
(list 1 2 3)
this is a call of the Common Lisp function LIST with three arguments 1, 2 and 3. Each of the arguments will be evaluated. Since they are numbers, they evaluate to themselves. When evaluated the result is a fresh new list (1 2 3).
Data sharing in compiled code
Imagine in a Lisp file the following four definitions:
(defparameter *list1* (list 1 2 3))
(defparameter *list2* (list 1 2 3))
(defparameter *list3* '(1 2 3))
(defparameter *list4* '(1 2 3))
Then we compile and load the file.
! (eq *list3* *list4*) now may evaluate to either T or NIL depending on the implementation and compiler settings !
Reason: in Common Lisp the Lisp compiler may share structure of literal lists (!) if they are similar. The compiler detects that here the lists are similar and will allocate only one list. Both variables *list1* and *list2* the will point to this one list.
All other EQ (object equality) comparisons of two of the above lists will return NIL.
Notations for some other data structures:
'(1 . 2) and (cons 1 2) ; cons cell
'#(1 2 3) and (vector 1 2 3) ; vector
'#S(FOO :a 1 :b 2) and (make-foo :a 1 :b 2) ; structure
One is the literal data and the other is a function call that constructs such a data structure.
Quoted lists (e.g. '(1 2 3)) should be treated carefully (generally as read-only). (see SO answers When to use 'quote in Lisp and When to use 'quote in Lisp).
(list 1 2 3) will "cons" up a fresh list, independent of all others.
You can see an example of a pitfall of using quoted lists in the manual for nconc.
And, as you probably know, when you call 'list - the arguments will obviously be evaluated versus the contents of a quoted list. And 'quote takes a single argument, versus 'lists variable number of arguments.
(list (+ 1 2) 3) --> (3 3)
(quote ((+ 1 2) 3)) --> ((+ 1 2) 3)
Their relation can be analogous to function invocation with 'function name' and funcall.
When you have no idea what function you'll get at runtime, you use funcall.
When you have no idea what element you may get at runtime, your use list.
For people like me who get confused because of existence of backquote and count it as quote tacitly.
backquote is not quote
It's a reader-macro that expands into quote, list or others:
(macroexpand ''(1 2));=> '(1 2)
(macroexpand '`(1 2));=> '(1 2)
(macroexpand '`(1 ,2));=> (list 1 2)
(macroexpand '`(1 ,#foo));=> (cons 1 foo)
(macroexpand '`(1 ,#foo 2));=> (cons 1 (append foo '(2)))