Why does this series of clojure commands return false and not true? What is the difference between the result of statement 1 "C" and 2 "(quote C)"?
; SLIME 2009-03-04
user> ('A 'B 'C)
C
user> (last '('A 'B 'C))
(quote C)
user> (= ('A 'B 'C) (last '('A 'B 'C)))
false
This question is somewhat similar to How does clojure's syntax-quote work?
In Clojure (and other Lisps) the ' is a shortcut for the form (quote ...). So when Clojure sees this:
('A 'B 'C)
which is "translated" by the reader into:
((quote A) (quote B) (quote C))
Each of those quote forms evaluates to a symbol, so (quote A) evaluates to the symbol named A. In Clojure, symbols are functions and can be applied, so ((quote A) (quote B) (quote C)) is actually a function call. From the docs:
"Symbols, just like Keywords, implement IFn for invoke() of one argument (a map) with an optional second argument (a default value). For example ('mysym my-hash-map :none) means the same as (get my-hash-map 'mysym :none)."
So what happens is that C is the default value and that's why it's returned.
Meanwhile, this
'('A 'B 'C)
is translated by the reader into
(quote ((quote A) (quote B) (quote C)))
Which is actually a list of three elements, each of which is a list of two elements, the symbol quote and another symbol (in this case A, B, C).
So, (last '('A 'B 'C)) is actually (quote C). That's the difference between those two results, C is the symbol with the name C while (quote C) is a list of two elements.
You can confirm this:
user=> (class ('A 'B 'C))
clojure.lang.Symbol
user=> (class (last '('A 'B 'C)))
clojure.lang.PersistentList
user=>
Hope that's clear!
('x 'y) is very unusual, for just this reason. Usually you want '(x y), which is a list of the literal symbols x and y. If you quote TWICE with '('x 'y), you get a list with (quote x) instead: the literal symbol quote, followed by the literal symbol x.
Related
I am writing a function that will take a list from a user and will flatten this list into one simplified list. The function seems to only return the first item on the list and not the rest? Any suggestions on why it is doing this?
Example:
> (flatten '(a () b (c d))
(a b c d)
This is what I have so far
(defun flatten (list)
(cond
((null list)t)
(list (first list) (rest list))
(t(append (flatten (first list))
(flatten (rest list)))
(t(cons (first list (flatten (rest list))))))))
The output it is giving
> (flatten '(a () b (c d)))
(NIL B (C D))
You are editing the original question with updated code, which makes it a moving target. Currently, your code is the following one, after I ask Emacs to indent it with M-q (lisp-mode):
(defun flatten (list)
(cond
((null list)t)
(list (first list) (rest list))
(t (append (flatten (first list))
(flatten (rest list)))
(t (cons (first list (flatten (rest list))))))))
;; ^^^ Something is not good, why is the clause indented?
Parentheses structure the code for the computer, whereas indentation is a way to print this structure for human readers. This redundancy allows you to detect problems in source code when one does not match the other. Here, the (t cons) is not a cond clause, it is nested inside the previous clause.
Second, as said in comments, cond will go to the first clause for which the test succeeds. If you wrote (cond (t X) ...), nothing in the ... part would change the meaning of the code, which always returns X. In your code, you test as follows:
(null list) tests whether list is eq to nil.
list does not test whether list is a list. There is a predicate named listp to detect that. When you put list alone like this, you are asking whether list is a generalized true value, which is necessarily true when you previously ruled out nil (the previous clause).
The default clause (t ...) has no way to be used, because the previous test cannot fail.
Here is a skeleton:
(defun flatten (form)
(cond
((null list) ...)
((consp list) ...)
(t ...)))
Instead of consp you could write listp, but note that by definition a list is either nil or a cons cell, so consp is a little more explicit and does not overlap with a test for nil. Note also that I always test against the type of form, which is a pattern that is often found. That's why you might prefer to use typecase.
I want to create following list in Lisp.
((lambda(x) (cons x x)) (cons'A 'B))
creates this list, but
((lambda(x y) (cons x y)) (cons'A 'B) (cons 'A 'B))
and
(cons (cons 'A 'B) (cons 'A 'B))
do not create the list.
My challenge is why!? How does the first command create this list and the others do not? Any detail?
Every time (cons 'A 'B) is called, a fresh cons cell is created, so your second two expressions create two "similar" (equal but not eql) objects (A . B),
You want to create a cons of A and B:
(cons 'A 'B)
Then you want to refer to it twice from another cons. So if x is a reference to this existing cons, you want
(cons x x)
Wrapping up, we get
(let ((x (cons 'A 'B)) (cons x x))
or equivalently
((lambda (x) (cons x x)) (cons 'A 'B))
If you do (cons 'A 'B) twice you create two cells:
AB
AB
and the cons of those will contain one link to the first, and another to the second.
(Using a lambda to refer to them is a pointless obfuscation; the point of the example with the lambda form is that you use x twice. The form
((lambda (x y) (cons x y)) (cons 'A 'B) (cons 'A 'B))
is just a very tedious way to write
(cons (cons 'A 'B) (cons 'A 'B))
whereas in the original example there is -- pointedly -- only one instance of (cons 'A 'B) which you want to be able to refer to twice.)
The purpose of this exercise is to illustrate the difference between "surface" equivalence and identity. Two lists which contain the same values are still two different lists, whereas two references to the same list are identical. As #sde hints, this makes a difference for understanding comparisons; the prototypical example is that equal is true for distinct lists containing the same values (as well as identical lists, of course), whereas eql is only true if its arguments are in fact identical (i.e. they refer to the same object).
'() is a syntax sugar for (quote ()). But what does '[] mean? Quote a vector?
For example:
(use '[clojure.test :as t])
(.get '[a b c] 1)
(.containsAll '[a b c] '[b c])
((fnth 5) '[a b c d e])
Precisely. ' is a synonym for quote, so
'[a b c]
is just
(quote [a b c])
quote prevents evaluation of a Clojure code, so quoting the whole vector is essentially the same as quoting every single element of it:
['a 'b 'c]
It allows you to produce a vector of symbols, without explicitly calling symbol function:
[(symbol "a") (symbol "b") (symbol "c")]
I want to get the second value of '(a b c) and I don't want to use cadr.
I can get the right answer:
(car (cdr '(a b c)))
'b
But when I built the function:
(define test (lambda (list) (car (cdr (list)))))
(test '(a b c))
I get the following error:
. . application: not a procedure;
expected a procedure that can be applied to arguments
given: '(a b c)
arguments...: [none]
I really don't know what's this error means.
There are incorrect parentheses in your code, surrounding the list parameter - in Scheme this: (f) means "apply the f function with no arguments", so in your code this: (list) is trying to invoke the list parameter as if it were a function, which is not, raising an error.
Also notice that it's a bad idea to call list the parameter, there's already a built-in procedure with that name; that's why I renamed it to lst. This should fix it:
(define test
(lambda (lst)
(car (cdr lst))))
(test '(a b c))
=> b
This is #7 of of 99 Lisp problems: transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). I have tried several solutions, e.g from #2680864 or from here. They all work, but I run into a problem if I am flattening a list containing a quoted element. E.g.:
> '(a 'b c)
(A 'B C)
> '(a (quote b) c)
(A 'B C)
> (flatten '(a 'b c))
(A QUOTE B C)
In the latter case I would like to get:
(A 'B C)
It seems that the internal representation of ' gets in the way for this task! SBCL, CLISP, ECL, ... they all behave the same way.
Quoted elements in a list? That usually does not make sense. Why would you have it quoted?
(a b c) is a list of three symbols. Why would you quote elements in the list? like in (a 'b c)? Why? What would be the purpose of the quote?
In Common Lisp ' is a readmacro which expands 'a into (QUOTE A). Since this is a normal list, a typical flatten operation will collect the symbols QUOTE and A into the flat list. This is because a flatten function typicall checks whether something is an atom or not. If you don't want this, your flatten function needs to check if something is an atom or a two-element list with QUOTE as its first symbol.
But as I said above, the default usage is just to flatten symbols, since quoted symbols are usually not useful inside a list. You need to extend the flatten function otherwise.
For example:
(defun flatten (l &key (test #'atom))
(cond ((null l) nil)
((funcall test l) (list l))
(t (loop for a in l nconc (flatten a :test test)))))
CL-USER > (flatten '(a (('b) c) ('d) )
:test (lambda (item)
(or (atom item)
(and (eq (first item) 'quote)
(null (cddr item))))))
(A (QUOTE B) C (QUOTE D))