How is each of the things different in cons of LISP? - lisp

These are the outputs of different combinations of arguments to cons. I just started learning lisp. Can someone help me understand these ?
Break 80 [81]> (CONS '(A) 'B)
((A) . B)
Break 80 [81]> (CONS '(A) '(B))
((A) B)
Break 80 [81]> (CONS 'A 'B)
(A . B)
Break 80 [81]> (CONS 'A '(B))
(A B)
Break 80 [81]>

The cons function always does the same thing: it produces a cons cell of its arguments. A cons cell is simply a pair. You can get the first element of the pair with car and the second element with cdr.
For writing a literal cell, you can quote and use the notation (x . y) where x is the car and y is the cdr. Using this notation, you can write your examples as follows (but don't just take my word for it, try it in the REPL):
> '((A) . B ) ;=> ((A) . B)
> '((A) . (B)) ;=> ((A) B)
> '( A . B ) ;=> (A . B)
> '( A . (B)) ;=> (A B)
But why don't the results of the second and fourth cases print the same way that we wrote them? There are special printing conventions for cons cells, because we use cons cells to implement linked lists.
Read 14.1.2 Conses as Lists for specifics, but a list is a cons cell whose car is the first element of the list, and whose cdr is the rest of the list (i.e., another list). That means that the list (1 2 3) is the same as (using the literal dotted pair notation) (1 . (2 . (3 . nil))). You can try that in the REPL:
> '(1 . (2 . (3 . nil))) ;=> (1 2 3)
That's a very useful printing (and input) convention for a language where lists are so fundamental. I've written more about this in an answer to other questions, too:
Dot notation in scheme
Recursive range in Lisp adds a period?

Related

Order Lists by CAR

I need to be able to compare two cars of a list to sort them im LISP.
Lists '(e d) (a b)
I want to compare the cars (e and a). This works using eql. If they don't match, I want to order the lists alphabetically, so (a b) (e d).
I'm missing the part where I can see which character is 'bigger', so the check if e or a should come first. I've tried converting them to ascii codes, but that doesn't work for (car a). Using arithmetic operators such as '<' and '>' also doesn't work. Does anyone have an idea on how to do this?
Use string> without symbol-name:
CL-USER 6 > (string> 'a 'b)
NIL
CL-USER 7 > (string< 'a 'b)
0
For the sake of completeness, here is how you should use it inside sort to achieve desired result (sort is destructive- modifies used sequence, so I also used copy-tree to avoid that effect):
(let ((data '((e d) (a b))))
(sort (copy-tree data)
(lambda (x y) (string< (car x) (car y)))))
((A B) (E D))
A symbol is distinct from a string.
CL-USER> (symbol-name 'foo)
"FOO"
A string (a sequence of characters) can be compared in the manner you seem to be interested in.
CL-USER> (string> "FOO" "BOO")
0
CL-USER> (string< "FOO" "BOO")
NIL

How to create (d . nil) in lisp

I am beginner in Lisp. There is a question that I cannot solve.
Show the simplest expression that Lisp will print out when you type the following
expression:
’(a b (c . e) (d . nil))
I tried (cons 'a (cons 'b (cons (cons 'c 'e) (cons (cons 'd nil)))))
However, it wouldn't create (d . nil).
So, is there any way to create such a dot pair?
Show the simplest expression that Lisp will print out when you type the following expression
The question does not ask you to create a dotted pair, but how the dotted pair is printed. I suppose this question aims at showing you that lists are just dotted pairs printed in a special way.
If you write this in a REPL:
'(a b (c . e) (d . nil))
The REPL replies:
(A B (C . E) (D))
You have the exact same output if you write:
'(a . (b . ((c . e) . ((d . nil) . nil))))
Basically, (a b) is the list made of a symbol a in front of a sublist (b), written (a . (b)). Here I am only talking about how forms are read. If you write them directly in the REPL, they will first be read, then evaluated, and in that case you will get an error. That's why in the examples are quoted: an expression being quoted is not evaluated, but returned as-is.
If you want to write code that, when evaluated, produces the cons-cell (0 . 1), you have to write this list:
(cons 0 1)
The above is a list of three elements, which could be written equally:
(cons . (0 . (1 . nil)))
Your interpreter will read this list (a symbol, two numbers) and evaluate the resulting form. That forms produces, at runtime, the following cons cell:
(0 . 1)

Common Lisp: first returns first, but last returns a list of last -- huh?

I'm not getting this first/last thing in Common-Lisp. Yes, I see how it works, but I don't get WHY it works that way.
Basically, to get the first item in a list, I can use (first mylist). However, if I want the last item, (last mylist) doesn't give me that; instead, it gives me a list containing the last item in my list!
(I'm using Clozure-CL, which has a few other oddities that seem like bugs to me but, since I'm a Lisp-n00b, I'm trying not to fall for the old "the interpreter is broken!" trick :) )
So, for example:
? (setq x '((1 2) (a b)))
=> ((1 2) (A B))
? (first x)
=> (1 2) ; as expected
? (last x)
=> ((A B)) ; why a list with my answer in it?!
? (first (last x))
=> '(A B) ; This is the answer I'd expect from plain-old (last x)
Can someone help me understand why last does this? Am I using these items incorrectly? Is first really the odd-ball?!
Thanks!
In Common Lisp last is supposed to return a list, from the documentation:
last list &optional n => tail
list---a list, which might be a dotted list but must not be a circular list.
n---a non-negative integer. The default is 1.
tail---an object.
last returns the last n conses (not the last n elements) of list. If list is (), last returns ().
For example:
(setq x (list 'a 'b 'c 'd))
(last x) => (d)
And yes, this is counterintuitive. In other flavors of Lisp it works as the name suggests, for example in Racket (a Scheme dialect):
(define x '((1 2) (a b)))
(first x) => '(1 2)
(last x) => '(a b)
(define x (list 'a 'b 'c 'd))
(last x) => 'd
Returning the last element is not very useful except to access the last element; returning the last cons lets you do something like this:
(let ((x (list 1 2 3)))
(setf (cdr (last x)) '(4))
x)
=> '(1 2 3 4)
while you can still access the last element as (car (last x)).
Common Lisp's misnamed function last gives you the last cons.
It should probably be called tail, as there is a function tailp, but my guess is that this name stuck for historical/compatibility reasons.
Generally, it gives you the nth tail of a list, or the nth cons before the end of the list.
This is just the way it is. first and last are not a complementary pair of operations. last is more closely related to rest and nthcdr. There is also butlast which constructs a new list that omits the last item from the given list.
first versus last is nothing compared to how get and getf have nothing to do with set and setf.

Recursive range in Lisp adds a period?

(define ..
(lambda (start stop)
(cond ((> (add1 start) stop) (quote ()))
((eq? (add1 start) stop) (sub1 stop))
(else (cons start (.. (add1 start) stop))))))
I have defined a simple range function.
The intent is for
(.. 1 5) --> (1 2 3 4)
Instead, a bizarre period is being added to my tuple and I have no idea why:
(.. 1 5) --> (1 2 3 . 4)
I don't understand why this is happening. Any help is appreciated
A list in Scheme is either the empty list () (also known as nil in some Lisps), or a cons cell whose car (also known as first) is an element of the list and whose cdr (also known as rest) is either the rest of the list (i.e., another list), or an atom that terminates the list. The conventional terminator is the empty list (); lists terminated by () are said to be "proper lists". Lists terminated by any other atom are called "improper lists". The list (1 2 3 4 5) contains the elements 1, 2, 3, 4, and 5, and is terminated by (). You could construct it by
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))
Now, when the system prints a cons cell, the general case is to print it by
(car . cdr)
For instance, the result of (cons 1 2) is printed as
(1 . 2)
Since lists are built of cons cells, you can use this notation for lists too:
'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))
That's rather clunky, though, so most lisps (all that I know of) have a special case for printing cons cells: if the cdr is a list (either another cons cell, or ()), then don't print the ., and don't print the surrounding parenthesis of the cdr (which it would otherwise have, since it's a list). So, if you're seeing a result like
(1 2 3 . 4)
it means you've got an improper list that is terminated by the atom 4. It has the structure
(1 . (2 . (3 . 4)))
Now the question is: where in your code did the list construction go awry? .. is always supposed to return a proper list, so let's look at the cases: The first case always returns a proper list (the empty list):
((> (add1 start) stop) (quote ()))
The second case looks like it can return something that's not a list (assuming that (sub1 stop) == (- stop 1)):
((eq? (add1 start) stop) (sub1 stop))
Now, if .. were functioning correctly, then the third case would always be returning a proper list (since (cons x y) is a proper list if y is):
(else (cons start (.. (add1 start) stop)))
Make your second case return a list and you should be all set.
Your expression (sub1 stop) needs to read (list (sub1 stop))
In order for cons to build up a proper list, the second element needs to be a list itself. Thus, your function .. should return a list of some type for every cond clause.
Remove this part of the cond
((eq? (add1 start) stop) (sub1 stop))
It's causing a premature finish.

LISP: Help reading input stream (with spaces) into a list of characters

I am attempting to write a program whereby I need to process a string character-by-character, including whitespace. This string would be given by the user running the program, from the standard input stream.
I have noticed that the (read) function stops only after some non-whitespace characters have been captured, and cuts off everything starting with the first whitespace character.
In other words if I do a (read) function and enter hi to you, it will return HI. What I would like my function to return is (#\h #\i #\Space #\t #\o #\Space #\y #\o #\u). Can anyone give me some pointers as to how to accomplish this? Sorry guys, I am VERY new to LISP but I like it a lot.
EDIT: One thing I've tried is using (cons) with (read-char). For example: (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) (read-char))))). When the user enters "hello", this outputs (#\h #\e #\l #\l . #\o), which is close, but what is that extra period doing in there?
Xach basically answered your main question: you'd probably want to read a line with read-line and coerce it to a list: (coerce (read-line) 'list) and then do something with this list.
The reason that read doesn't work is that it reads and returns s-expressions:
> (car (read))
(foo bar baz) ; this is me typing
FOO
So it just reads the first symbol hi in the input "hi to you" and stops. Successive calls to read will return the rest:
> (list (read) (read) (read))
hi to you ; me typing again
(HI TO YOU)
You probably still want to use Xach's suggestion to get your input though.
To address your other question, the reason there's a dot in that list of characters is that the expression (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) (read-char))))) ends with (cons (read-char) (read-char)) which conses two characters together.
Cons creates "cons cells" or Lisp pairs, which are represented as a dotted pair:
> (cons 'a 'b)
(A . B)
Lisp lists are usually formed with nil or the empty list as the last element. But they are actually represented as linked lists with these cons cells, these are the same:
(a . (b . (c . ())))
(a b c)
They are just usually printed the second way. In your case, the last element is a character, so it's printed as a dotted tail list. Experiment with it at the REPL and it will make sense:
> '(a . (b . c))
(A B . C)
> '(a b . c)
(A B . C)
> '(a b c)
(A B C)
> '(a . (b . (c . nil)))
(A B C)
So what you would want to do with that original expression is this:
> (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) nil)))))
(#\h #\e #\l #\l #\o)
read-char will return the next available character, and read-line will return an entire line of input as a string. You can use coerce to change a string to a list of characters, e.g.
(coerce "foo" 'list) => (#\f #\o #\o)