Can you explain why the first one is false and the second one is true?
And how this works? Thanks.
(eq? '(1 2 3) '(1 2 3)) ;False
(eq? '() '()) ;True
There's only one empty list, so all uses of () refer to that list, and it's eq? to itself. The Scheme Specification description of the storage model says:
Notwithstanding this, it is understood that the empty list cannot be
newly allocated, because it is a unique object.
and the specification of eqv? (which is referenced by the eq? description) says that two objects are equivalent if
obj1 and obj2 are both the empty list
But when you create a non-empty list, it creates a fresh one every time, and they're not eq? to each other even if they contain the same elements.
Quoted from TSPL3:
[..] Two objects are considered identical if they are represented internally by the same pointer value
[..] The empty list () is identical to itself wherever it appears.
[..] Two pairs, vectors, or strings created by different applications of cons, vector, string, etc., are distinct.
If you write instead
(let ((x '(1 2 3)))
(eq? x x))
it will be #t.
Related
I am writing an interpreter for R7RS Scheme to gain a more complete understanding of the Scheme programming language.
From my understanding, eqv? must return #t if both list arguments denote the same location in memory. However, I am not sure if the cdr of a list must always be eqv:
(define l '(a b c))
(eqv? (cdr l) (cdr l)) ; #t of #f?
The missing part of my knowledge is whether or not the cdr of a particular list must always point to a particular location. For a particular list, must cdr always return an identical sublist every time it is called on the list, or can it return a completely new sublist?
(I understand that I can test this empirically using existing Scheme interpreters, but I am mainly interested in what the standard mandates).
eq? is pointer equality (symbol, boolean, empty list)
eqv? is #t for everything that is eq? and the same primitive value (number, char)
equal? is #t for everything that is eqv? and values that look the same
cdr is an accessor. (cdr l) will return the same pointer and thus (eq? (cdr l) (cdr l)) ; ==> #t and so will eqv? and equal? since they are guaranteed #t when a lower level equality predicate is.
Note that is is not the other way around. eg. (equal? "test" "test"); ==> #t but (eqv? "test" "test") can be either #f or #t. The cause of the different behavior is if you reuse constant data when you read the code rather then create new.
It's common to store primitive values in the pointer. Eg. on a 64 bit machine the last 3 bits is always 0 since we access the words aligned. Scheme implementation usually then code 0-7 to indicate type and often when it's 0 the rest of the bits isn't a location at all rather than a number embedded in the pointer. This way you can have a list (1 2 3) that uses 6 words. 3 pairs of 2 words each but no memory used for the numbers when they fit the 61bit size. This is why numbers and char are often eq? while not guaranteed in the report.
In The Little Schemer (4th Ed.) it is claimed that a list for which null? is false contains at least one atom, or so I understand from my reading of the text.
This doesn't make sense to me, since (atom '()) is false, and we can stick those into a list to make it non-null:
> (null? '(()))
#f
So my question is, is this a mistake in my reading, or a matter of definitions? Since it's not in the errata I assume such a well-studied book wouldn't have a mistake like this.
If we considered (()) to be the same as (() . ()) or even (cons '() '()) and then considered cons an atom then I could see how you can get there, but I don't think that's what's going on.
(this was tested in Racket 7.0, with the definition of atom? given in the book, i.e.
(define atom?
(lambda (x)
(and (not (pair? x)) (not (null? x)))))
I know this doesn't cover funny Racket features, but should be sufficient here.)
lat is assumed to be a list of atoms at that point in the book.
If it's not empty, by definition it contains some atoms in it.
It's not about Lisp, it's about the book's presentation.
I think lat indicates list of atoms. Thus if lat is not null?, then it needs to contain at least one atom.
There is a procedure called lat? defined as such:
(define lat?
(lambda (l)
(cond
((null? l) #t)
((atom? (car l))
(lat? (cdr l)))
(else #f))))
(lat? '(()) ; ==> #f so by definition '(()) is not a lat and thus the statement does not apply to that list.
A list can contain any type of elements, including empty and other lists, both which are not atoms. lat is a restricted to a flat list with only atomic elements.
As a concept an “atom” is something that can not be broken into smaller parts. A number 42 is an atom, a list (42 43) is not an atom since it contains two smaller parts (namely the numbers 42 and 43). Since an empty list does not contain any smaller parts, it is by this logic an atom.
Now let’s attempt to implement an atom? predicate, that determines whether it’s input is an atom.
(define (atom? x)
(cond
[(number? x) #t]
[(symbol? x) #t]
[(char? x) #t]
...
[else #f]))
Here the ... needs to be replaced with a test for every atomic data type supported by the implementation. This can potentially be a long list. In order to avoid this, we can try to be clever:
(define (atom? x)
(not (list? x)))
This will correctly return false for non-empty lists, and true for numbers, characters etc. However it will return false for the empty list.
Since it is up to the authors of the book to define the term “atom” (the word does not appear in the language standard) they might have opted for the above simple definition.
Note that the definition as non-list is misleading when the language contains other compound data structures such as vectors and structures. If I recall correctly the only compound data structure discussed in the book is lists.
I know cons is for building pairs, like (cons 2 (cons 3 empty)), but I don't understand the code here that use cons after empty. Isn't cons built for numbers? How can cons take 2 arguments? If they can take 2 arguments, how does it evaluate them? and can someone please translate the code after [(empty? lst) empty] please.
(define (removed2 lst)
(cond
[(empty? lst) empty]
[(not (member? (first lst) (rest lst)))
(cons (first lst) (removed2 (rest lst)))]
[else (removed2 (rest lst))])
I suggest you read a good book or a tutorial on Scheme, you're asking for explanations of some of the most basic concepts, that should be well-understood before starting to code in Scheme. For instance, this chapter is a great starting point. I'll address your questions:
I know cons is for building pairs, like (cons 2 (cons 3 empty))
Indeed, you can build pairs of anything you want… pairs of numbers, pairs of pairs, you name it.
But I don't understand the code here that use cons after empty.
In this case, empty means the empty list '(). So, we can build a pair where the first element is an atom (a number in this case) and the second is an empty list - and that's how we build proper lists in Scheme!
Isn't cons built for numbers?
No, it's for building pairs of anything, including other pairs.
How can cons take 2 arguments? If they can take 2 arguments, how does it evaluate them?
And why not? as you've already stated, cons is for building pairs. A pair is made up of two things, so cons takes 2 arguments. It evaluates each of them in turn and then sticks them together to form a pair. You should really, really read the documentation.
And can someone please translate the code after [(empty? lst) empty] please
That's just asking if the list we're recursively traversing is empty, if it is, then it returns an empty list - the base case of any recursive procedure that returns a list. The procedure is simply building a list as a result, for that is consing elements to pairs, and the last pair ends with an empty list, producing a proper list. Basically, this is how you build a list in Scheme:
(cons 1 (cons 2 (cons 3 empty)))
=> '(1 2 3)
This is probably a simple thing I'm missing, but I'm trying to get the cdr of a pair and every call to say (cdr (cons 'a '5)) comes back as (5). I sort of get why that is, but how can I get the it to return without the parens?
I don't want to use flatten because what I'm trying to get (i.e. the cdr) might itself be another procedure expression already wrapped in parens, so I don't want to flatten the list.
(If it matters, I'm working on transforming a let expression into a lambda expression, and this is one of the steps I'm taking, trying to break apart the lambda bindings so I can move them around).
When applied to a proper list, cdr will always return another list (including '(), the empty list).
With proper list I mean a list which ends with the empty list. For instance, when you do this (define lst '(4 5)) under the hood this is what gets assigned to lst: (cons 4 (cons 5 '())), so when you evaluate (cdr lst) you get the second element of the first cons, which happens to be (cons 5 '()), which in turn gets printed as (5).
For extracting only the second element in the list (not the second element of the first cons, which is what cdr does) you could:
As has been pointed in the comments, use (car (cdr lst)) or just (cadr lst) for short
Even simpler: use (second lst)
Another possibility - if the list only has two elements and it's ok to replace it with an improper list, use (define cell (cons 4 5)) or (define cell '(4 . 5)) to build a cons cell and then you can use (car cell) to extract the first element and (cdr cell) to extract the second element.
I am having trouble writing a function that will move the first element to the end of the list every time it is called. I have tried using a combination of reverse and cdr to cut off the elements at either end, but cannot figure out how to add the elements to the correct end. Any help would be appreciated. Thanks!
Correct outcomes:
(first_to_last '(1 2 3))
(2 3 1)
(first-to-last (first-to-last '(1 2 3)))
(3 1 2)
I think you're over-doing the reversing, personally.
What we want is a list consisting of cdr x with car x appended to the end. The one trick here is that car x isn't a list, so we want to convert it to a list before appending it:
(define (first-to-last x) (append (cdr x) (list (car x))))
If you wanted to stick to the fundamentals, cons is the really fundamental way to put things together into lists, but it would be a bit more work. You'd basically end up defining something essentially identical to append in terms of cons. That's pretty easy but kind of pointless, given that append already exists.
Edit: I guess if you want to use reverse for some reason or other, you could do something like this:
(define (first-to-last x) (reverse (cons (car x) (reverse (cdr x)))))
It's a bit longer and strikes me as kind of clumsy, but it ought to work anyway.