what's the difference of the two list in scheme - list

I'm a newbie to scheme. I'm just confused about the difference of the following two list.
(define a '(1 2))
(define a '(1 . 2))
I think a equal to b, but
(equal? a b)
return #f to me.
Any help will be greatly appreciated.

The two aren't the same. The first is a normal list. In dotted notation it would look like this:
(1 . (2 . nil))
A normal list stores data in the car of a cons cell, and the cdr is only used to store a pointer to the next cons cell in the list, or Nil for the last cell in the list.
Your definition of a uses only one cons cell, with 1 in the car and 2 in the cdr.
If you drew them out graphically, they'd look like this:

The "dot" notation is used in Scheme and LISP to describe "improper lists", those that don't follow the standard list data definition. This question:
Functional Programming: what is an "improper list"?
... probably answers most of your questions. Let me know if there's anything this post doesn't answer.
Good luck!

They don't return equal because they are not the same data type. the first one with: (define a '(1 . 2)) is what is known as a pair. A list is a pair but not all pairs are lists. Lists are pairs that have a car and their cdr is a list. When you get the dot notation it means that the car of that pair is 1 and the cdr is 2. Since they aren't the same data type, they can't be equal.

Related

LISP: Reversing a dotted list

There is a question in Common Lisp: A Gentle Introduction. The question is to get the last element in the list instead of cons cell. The macro LAST returns the cons cell in a dotted list. The question asked is to use the macro reverse instead of last, but both clisp and sbcl are throwing error.
(reverse '(a b c . d))
=> error
CLHS documentation says that we can reverse only a proper list (sequence) and not a dotted list or a circular list.
EDIT
I have written the program using LAST.
(defun last-element (x)
"x is a list with last element as dotted pair"
(cdr (last x)))
I am not sure how to use reverse in such a situation.
The function last returns the last cons cell for any proper list or dotted list, so long as the list is not circular.
It sounds like the question is about Exercise 6.6:
Use the LAST function to write a function called LAST-ELEMENT that returns the last element of a list instead of the last cons cell. Write another version of LAST-ELEMENT using REVERSE instead of LAST. Write another version using NTH and LENGTH.
The exercise would have specified dotted list input if that was the intention. When list is used in an unqualified way, it almost always means proper list. For a proper list last will return a cons cell with nil in the cdr, e.g., (last '(a b c d) --> (d . nil), or just (d), so the last element of a proper list is the car of the last cons cell.
If you want to handle both proper and dotted lists, you need to determine which the input is and handle it accordingly: for a dotted list the last "element" would be the cdr of the last cons cell. Handling the inputs accordingly for the reverse version means that you must determine whether the input is a proper list or a dotted list before applying reverse. You could write a function to convert a dotted list to a proper list before using reverse.
Technically speaking, the Standard does not consider the atom which terminates a dotted list to be one of its elements:
element n. 1. (of a list) an object that is the car of one of the conses that comprise the list.
For a proper list like (a b c d), nil is the terminating atom (since (a b c d) is identical to (a b c d . nil)), and (d . nil) is the last cons; d is the car of the last cons, and is thus the last element of the list. For a dotted list like (a b c . d), d is the terminating atom, and (c . d) is the last cons. Since c is the car of the last cons, c is the last true element, in the sense defined in the Standard, of the dotted list. It would probably be more accurate to say that d is the last member of (a b c . d).
But, Exercise 6.6 in Common Lisp: A Gentle Introduction is meant for proper lists only.

How can I make equivalence function in Common Lisp?

I know that it is possible to check if 2 lists have the same sets with using "EQUAL" function in Common Lisp.
(equal '(a b c) '(a b c)) => T
(equal '(a b c) '(b c a)) => T
(equal '(a b c) '(d e f)) => NIL
But you know, it is impossible if the two lists have the same sets if the sets are arranged in different orders.
I guess that it may be possible to make the function which can predicate that tests whether two sets contain the same elements even if they are arranged in different orders with using 'remove' function and recursion. But, I can't concrete my idea to make this function exactly.
How can I realize the idea?
A solution that does exactly this can be found here. The OP of that question has a working solution, and the accepted answer is a better solution.
What I will do is try to explain the logic.
Let's step through this problem first. You're given 2 lists, list1 and list2.
If list1 is null, then return true if list2 is also null. ( You don't need to check the opposite of this, that gets taken care of in step 2 )
Else (list is not null/empty): We have to somehow, as you suggested, remove an element that is in both sets. This can be achieved by letting list3 be a list such that it is list2 with the first item in list1 removed.
i. If nothing is removed, i.e, then list2 and list3 are equal (you can use normal equal here), and so the function returns false, because it finds an element in list1 that is not in list2
ii. If something is removed then call our function again on the (rest of list1) and list3.
If you want to use built-in CL facilities, you can use set-exclusive-or like this:
(defun sets-equivalent (set-a set-b)
(not (set-exclusive-or set-a set-b)))
Per CLHS:
set-exclusive-or returns a list of elements that appear in exactly one of list-1 and list-2.
So if returned list is empty, it means sets are equivalent.

Remove a specific item in a list?

I want to preface this by saying that yes, this is a homework problem I'm working on and I don't want the actual answer, just maybe a nudge in the right direction. Anyhoo, I'm taking a class on programming languages' structures, and one of our projects is to write a variety of small programs in lisp. This one requires the user to input a list and an atom, then remove all instances of the atom from the list. I've scoured the internet and haven't found all that many good lisp resources, so I'm turning to you all.
Anyways, our professor has given us very little by way of stuff to work off of, and by very little I mean practically nothing.
This is what I have so far, and it doesn't work.
(defun removeIt (a lis)
(if (null lis) 0
(if (= a (car lis))
(delete (car lis))
(removeIt (cdr lis)))))
And when I type
(removeIt 'u '(u e u e))
as the input, it gives me an error stating it got 1 argument when it wanted 2. What errors am I making?
First, a few cosmetic changes:
(defun remove-it (it list)
(if (null list) 0
(if (= it (car list))
(delete (car list))
(remove-it (cdr list)))))
Descriptive and natural sounding identifier names are preferred in the CL community. Don't be shy to use names like list – CL has multiple namespaces, so you don't have to worry about clashes too much. Use hyphens instead of camel case or underscores. Also, read a short style guide.
You said you didn't want the answer but helpful tips, so here we go:
Check your base case – your result will be a list, so why do you return a number?
Use the appropriate comparison function – = is for numbers only.
You are building a new result list, so no need to delete anything – just don't add to it what you don't want.
But remember to add what you want – build your result list by consing what you want to keep to the result of applying your function to the rest of the list.
If you don't want to keep an element, just go on applying your function to the rest of the list.
You defined your function to take two arguments, but you're calling it with (cdr list) only. Provide the missing argument.
I've scoured the internet and haven't found all that many good lisp
resources,
Oh, come on.
Anyhow, I recommend Touretzky.
By the way, the function you're trying to implement is built-in, but your professor probably won't accept it as a solution, and doing it yourself is a good exercise. (For extra credit, try solving it for nested lists.)
This is a good case for a recursive function. Suppose there exists already a function called my-remove which takes an atom and a list as arguments and returns the list without the given atom. So (my-remove 'Y '(X Y Z)) => '(X Z)
Now, how would you use this function when instead of the list '(X Y Z) you have another list which is (A X Y Z), i.e. with an element A in front?
You would compare A to your atom and then, depending on whether the element A matches your atom, you would add this element A or not to the result of applying remove to the rest of the list.
With this recursion the function my-remove will be called successively with shorter lists. Now you only have to think about the base case, i.e. what does the function my-remove have to return when the list is empty.
This is an answer for other people looking specifically for elisp. A builtin function exists for this purpose called delq
Example
(setq my-list '(0 40 80 40 90)) ;; test list
(delq 40 my-list) ;; (0 80 90)
If you installed emacs from source you can check out how it is implemented by doing Mx find-function delq

Trying to reverse a list in Scheme

Be forewarned: this is a homework problem. I'm trying to write a Scheme function that reverses a list. '(1 2 3) becomes '(3 2 1), etc. I'm not allowed to use the predefined function that does this.
Am I on the right track with what I wrote here?
;myReverse
(define (myReverse list)
(if (null? list) '()
(append (myReverse(cdr list)) car list)))
Thanks!
Well, using list as an name is going to be odd, since Scheme is a Lisp-1. Call it lst instead.
Think about what you can do with foldl, cons, '(), and lst.
Am I on the right track with what I wrote here?
Yes. Some things to consider:
list is a built-in function name, and one you might actually want to use in this solution, so you probably shouldn't name your formal that
You forgot the parentheses around car list
append expects two lists; you're passing it a list and a number
> (append '(1) 2)
(1 . 2)
> (append '(1) '(2))
(1 2)

LISP very simple list question

Im learning lisp and im pretty new at this so i was wondering...
if i do this:
(defparameter *list-1* (list 1 2))
(defparameter *list-2* (list 2 3))
(defparameter *list-3* (append *list-1* *list-2*))
And then
(setf (first *list-2*) 1)
*list-3*
I will get (1 2 1 4)
I know this is because the append is going to "save resources" and create a new list for the first chunk, but will actually just point to the second chunk, coz if i do:
(setf (first *list-1*) 0)
*list-3*
I will get (1 2 1 4) instade of the more logical (0 2 1 4)
So my question is, what other cases are like this in lisp, how do you black belt lispers know how to deal with this stuff that is not intuitive or consistent?
One defensive tactic is to avoid sharing structure.
(defparameter *list-3* (append *list-1* *list-2* '()))
or
(defparameter *list-3* (append *list-1* (copy-list *list-2*)))
Now the structure of the new *list-3* is all new, and modifications to *list-3* won't affect *list-2* and vice versa.
The append function has to make a copy of its first argument, to avoid modifying existing data structures. As a result, you now have two list segments that look like (1 2 ...), but they're part of different lists.
In general, any list can be the tail of any other list, but you can't have a single list object that serves as the head of multiple lists.
You have to think of lists in terms of cons cells. When you define list 1 and list 2, it is like:
(defparameter *list-1* (cons 1 (cons 2 nil)))
(defparameter *list-2* (cons 2 (cons 3 nil)))
Then, when you append:
(defparameter *list-3* (cons 1 (cons 2 *list-2*)))
Basically, a cons cell consists of two parts; a value (the car), and a pointer (the cdr). Append is defined to not change the first list, so that is copied, but then the last cdr (normally nil) is changed to point at the second list, not a copy of the second list. If you were willing to destroy the first list, you would use nconc.
Try this:
(defparameter *list-3* (nconc *list-1* *list-2*))
Then observe the value of *list-1*, it is (1 2 2 3), just like *list-3*.
The general rule is that the non-destructive functions (append) won't destroy existing data, while the destructive functions (nconc) will. What a future destructive function does ((setf cdr)), though, is not the responsibility of the first non-destructive function.
quote:
So my question is, what other cases are like this in lisp, how do you black belt lispers know how to deal with this stuff that is not intuitive or consistent?
I think that you are a bit harsh here with a subject that is quite a bit larger than you imagine. Lists are a rather elaborate concept in Lisp, and you need to understand that this is not some simple array. The standard provides a lot of functions to manipulate lists in every way. What you want in this case is:
(concatenate 'list *list-1* *list-2*)
So, why is there also append? Well, if you can omit copying the last list, and all symbols involved still return the correct data, this can be a significant performance boost in both calculating time and memory footprint. append is especially useful in a functional programming style which doesn't use side effects.
In lieu of further explanation about cons cells, destructive vs. nondestructive functions etc., I'll point you to a nice introduction: Practical Common Lisp, Ch. 12, and for a complete reference, the Common Lisp Hyperspec, look at Chapters 14 and 17.
So my question is, what other cases are like this in lisp, how do you black belt lispers know how to deal with this stuff that is not intuitive or consistent?
By reading the fine manual? Hyperpsec explicitly states:
[...] the list structure of each of lists except the last is copied. The last argument is not copied; it becomes the cdr of the final dotted pair of the concatenation of the preceding lists, or is returned directly if there are no preceding non-empty lists.
Um, primarily we learn how it works, so that what we imagine isn't consistent makes sense.
What you need to do is find some of the old-fashioned block and pointer diagrams, which I can't easily draw, but let's figure it out.
After the first defparameter, you've got list-1, which is
(1 . 2 . nil)
in dot notation; list-2 is
(2 . 3 . nil)