Clojure: how to convert cons to list - clojure

(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

Related

(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.

Putting a list in a parameter in scheme

So I am new to using Scheme/Guile and have an assignment where I must take 2 inputs; a simple variable and a list.
I then add the variable to each number in the list and print it out. I have got it to load but when I enter this:
(add 1 (1 2 3))
I get this error:
Backtrace:
39: 0* [add 1 ...
39: 1* [1 2 3]
standard inout:39:8: In expression (1 2 3):
standard input:39:8:wrong type to appy: 1
ABORT: (misc-error)
Here is the code that I currently have.
(define a (list a))
(define (add y a)
(define x 0)
(while (< x (length a))
(display (+ y (car a)))
(newline)
(set! a (cdr a))
(set! x (+ x 1))
)
)
My question is:
How do I get the list to work in the parameter? I have looked around online but havent found much to fix this problem.
Many thanks ahead of time for any help you can give me.
You're getting an error because (1 2 3) tells it to call the function 1 with two arguments, 2 and 3. To create a list containing 1, 2 and 3, use (list 1 2 3).
Do you really intend to write a procedure in such an imperative way? It looks not very Scheme-like. Evaluating your procedures in GNU Guile yields many error messages about unbound variables etc. set! is eval for beginners of Scheme ;) :) (SICP treats assignment extensively in chapter 3). You can do it much easier in functional style without the side-effects of set! and display.
If you are already aware about mapping and high-order functions, you could do something like this:
(define (add x)
(lambda (y) (+ x y)))
(map (add 1) (list 1 2 3))
===> (2 3 4)
If not, write a recursive procedure yourself:
(define (add-to-list x list)
(if (null? list)
'()
(cons (+ x (car list))
(add-to-list x (cdr list)))))
(add-to-list 1 '(1 2 3))
===> (2 3 4)
In order to learn thinking recursively, consult books like SICP, HTDP or "The litte Schemer".

How to get a PersistentList from a Cons?

I am loading forms from a file using slurp, read, and cons'ing them together to recursively read all forms into a collection. Then wish to pass this into scriptjure's (js [& forms]) function, which expects a (list?), but (cons) gives me a Cons classed-object. How may I convert (class (cons 1 '(2 3 4 5))) to be IPersistentList? Thanks!
Use (apply list x) to create a list from sequence x :
user=> (class (apply list (cons 1 '(2 3 4 5 6))))
clojure.lang.PersistentList
Alternatively, if you start with a list and then conj forms onto it, you'll end up with a list:
user=> (class (conj (list 1 2 3) 4))
clojure.lang.PersistentList
No need for cons in this case since conj, given a list, returns a list.

setf in Clojure

I know I can do the following in Common Lisp:
CL-USER> (let ((my-list nil))
(dotimes (i 5)
(setf my-list (cons i my-list)))
my-list)
(4 3 2 1 0)
How do I do this in Clojure? In particular, how do I do this without having a setf in Clojure?
My personal translation of what you are doing in Common Lisp would Clojurewise be:
(into (list) (range 5))
which results in:
(4 3 2 1 0)
A little explanation:
The function into conjoins all elements to a collection, here a new list, created with (list), from some other collection, here the range 0 .. 4. The behavior of conj differs per data structure. For a list, conj behaves as cons: it puts an element at the head of a list and returns that as a new list. So what is does is this:
(cons 4 (cons 3 (cons 2 (cons 1 (cons 0 (list))))))
which is similar to what you are doing in Common Lisp. The difference in Clojure is that we are returning new lists all the time, instead of altering one list. Mutation is only used when really needed in Clojure.
Of course you can also get this list right away, but this is probably not what you wanted to know:
(range 4 -1 -1)
or
(reverse (range 5))
or... the shortest version I can come up with:
'(4 3 2 1 0)
;-).
Augh the way to do this in Clojure is to not do it: Clojure hates mutable state (it's available, but using it for every little thing is discouraged). Instead, notice the pattern: you're really computing (cons 4 (cons 3 (cons 2 (cons 1 (cons 0 nil))))). That looks an awful lot like a reduce (or a fold, if you prefer). So, (reduce (fn [acc x] (cons x acc)) nil (range 5)), which yields the answer you were looking for.
Clojure bans mutation of local variables for the sake of thread safety, but it is still possible to write loops even without mutation. In each run of the loop you want to my-list to have a different value, but this can be achieved with recursion as well:
(let [step (fn [i my-list]
(if (< i 5)
my-list
(recur (inc i) (cons i my-list))))]
(step 0 nil))
Clojure also has a way to "just do the looping" without making a new function, namely loop. It looks like a let, but you can also jump to beginning of its body, update the bindings, and run the body again with recur.
(loop [i 0
my-list nil]
(if (< i 5)
my-list
(recur (inc i) (cons i my-list))))
"Updating" parameters with a recursive tail call can look very similar to mutating a variable but there is one important difference: when you type my-list in your Clojure code, its meaning will always always the value of my-list. If a nested function closes over my-list and the loop continues to the next iteration, the nested function will always see the value that my-list had when the nested function was created. A local variable can always be replaced with its value, and the variable you have after making a recursive call is in a sense a different variable.
(The Clojure compiler performs an optimization so that no extra space is needed for this "new variable": When a variable needs to be remembered its value is copied and when recur is called the old variable is reused.)
For this I would use range with the manually set step:
(range 4 (dec 0) -1) ; => (4 3 2 1 0)
dec decreases the end step with 1, so that we get value 0 out.
user=> (range 5)
(0 1 2 3 4)
user=> (take 5 (iterate inc 0))
(0 1 2 3 4)
user=> (for [x [-1 0 1 2 3]]
(inc x)) ; just to make it clear what's going on
(0 1 2 3 4)
setf is state mutation. Clojure has very specific opinions about that, and provides the tools for it if you need it. You don't in the above case.
(let [my-list (atom ())]
(dotimes [i 5]
(reset! my-list (cons i #my-list)))
#my-list)
(def ^:dynamic my-list nil);need ^:dynamic in clojure 1.3
(binding [my-list ()]
(dotimes [i 5]
(set! my-list (cons i my-list)))
my-list)
This is the pattern I was looking for:
(loop [result [] x 5]
(if (zero? x)
result
(recur (conj result x) (dec x))))
I found the answer in Programming Clojure (Second Edition) by Stuart Halloway and Aaron Bedra.

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)))