What does the letter 't' mean in LISP?
ex:
(defun last2 (lst)
(cond ((null lst) nil)
((null (cdr lst)) (car lst))
(t (last2 (cdr lst)))))
My textbook is a coursepack so it doesn't quite explain all the meanings.
Thanks.
T is the canonical true value in Common Lisp. Here it is being used as an ELSE, ensuring that the last branch of the COND is always true. (Any value other than NIL counts as true as well.)
See the glossary of the Common Lisp Hyperspec for t.
t n. 1. a. the boolean representing true. b. the canonical generalized boolean representing true. (Although any object other than nil is considered true as a generalized boolean, t is generally used when there is no special reason to prefer one such object over another.) ...
Related
In working through the CLRS Intro to Algorithms book and attempting to implement a red-black binary search tree in common lisp, I came across the following issue with circular pointers:
(defstruct node (ptr nil))
(defparameter *x* (make-node))
(defparameter *y* (make-node :ptr *x*))
(setf (node-ptr *x*) *y*)
This code leads to a heap-exhausted-error, presumably due to an infinite recursion caused by having a pointer to a pointer which points back to that pointer, etc.
Is there a way to prevent this infinite recursion from happening while maintaining the pointer structure given here?
I know there are other ways to implement red-black trees (without using setf, for example), but I am interested in reproducing the imperative style in CLRS as common lisp is a multi-paradigm language.
PS. The BST in CLRS have parent pointers in addition to the usual left-child and right-child pointers.
There is no problem with circularity in Lisp. Common Lisp even has a special syntax for expressing it at read-time: For instance something like #1=(#1# . #1#) is a cons, both of whose elements are the cons itself: you could construct this explicitly by an expression like
(let ((c (cons nil nil)))
(setf (car c) c
(cdr c) c))
However there is a problem when printing structure which may contain circularity. In order to do this correctly you need something called an occurs check: as you are printing objects (in particular objects which have components) you need to keep track of whether you have seen this object already, and if you have you arrange to print a reference, which CL does by printing #n#, where n is an integer which tells the reader -- both the human reader and the Lisp reader -- which object this corresponds to, so they/it can reconstruct the structure, including its sharing. What's worse is that you have to either annotate each possibly-shared object (with #n=) when you start printing it, which would be terrible, or avoid printing anything until you have run over all the objects to know which ones you need to so annotate.
An occurs check is computationally expensive in space (or it seemed so in the 1980s when CL was being standardised: it still can be for very large structures of course), so it is not the default behaviour of the CL printer, but it is controlled by a special variable *print-circle*: if this is true then circularity (and in fact general shared-structure) detection is done by the printer; if it is false, it is not, and the printer may loop or recurse unboundedly when printing circular structure.
Note that the problem is more general than circularity: how should this object be printed:
(let ((c1 (cons nil nil))
(c2 (cons nil nil)))
(setf (car c1) c2
(cdr c1) c2))
Well, we can construct this explicitly like this:
(#1=(nil) . #1#)
And this is how it will be printed, if *print-circle* is true, because in that case the reader detects shared structure and prints it properly. Here is a demonstration of all this:
(let ((unshared (cons (cons nil nil) (cons nil nil)))
(shared (cons (cons nil nil) nil))
(circular (cons nil nil)))
;; construct the sharing explicitly rather than via syntax
(setf (cdr shared) (car shared)
(car circular) circular
(cdr circular) circular)
(with-standard-io-syntax
(let ((*print-circle* nil)) ;it is anyway
;; don't print cicrular!
(pprint unshared)
(pprint shared))
(let ((*print-circle* t))
(pprint unshared)
(pprint shared)
(pprint circular)))
;; be careful not to return anything possibly toxic to the printer
(values))
This will print
((NIL) NIL)
((NIL) NIL)
((NIL) NIL)
(#1=(NIL) . #1#)
#1=(#1# . #1#)
Note that certain very old Lisps (notably InterLisp) used reference-counting for storage management and while the language had no problems with circularity the reference-counter did. I'm sure no modern language uses reference-counting however.
Hey guys I need help with lisp function. I am supposed to create:
(myLast L)
Evaluates to the last element of list L.
eg. (myLast ‘(p a e g)) → g
I cant use all of the predefined forms for lisp only the ones we have been given in class:
(atom X)
(quote X)
‘X
(eq X Y)
(cons X L)
(car L)
(cdr L)
(list A B C)
(if X Y Z)
(cond (C1 S1) (C2 S2) …… (Cn Sn))
I thought I had it right when I put in:
(defun myLast (L)
(if ((eq L '()) (cdr L))
(car L)
(myLast (cdr L))))
However I am getting an error:
Error: The variable MYHW4.LISP is unbound.
Error signalled by EVAL
Backtrace: EVAL
Broken at SYSTEM::GCL-TOP-LEVEL.
I am completely new to LISP and trying to complete this assignment. I was hoping you guys could help me out and let me know why I am getting this error, and is my logic for the last functional form correct? Thanks!
There are multiple problems with your code.
You have excess parentheses. ((eq L '()) is not allowed as the only expression allowed at operator position is an anonymous function.
Your if only have a consequence expression but not a alternative. It isn't the last expression so it's dead code.
The you do car, also not in real position so far code also.
Tail expression is the recursion and is done unconditionally. It's called infinite recursion.
I think perhaps you meant something like this:
(defun myLast (list)
(if (null (cdr list))
(car list)
(myLast (cdr list))))
The error message is unrelated to your code. You probably typed (load myhw4.lisp) without quotes in which case your Lisp rightly think that you wanted to take the value bound to the variable myhw4.lisp, which does not exist. You need to quote strings "like so".
Also, ((eq L '()) ...) is problematic, since the first form is (eq ...) which is not a function or a lambda. That will signal an error..
The above makes your code wrong, but you are not far from it.
I'm going through the Structure and Interpretation of Computer Programs MIT video lecture series, and I had a quick question about returning side-effects from functions.
In video 3A, the professor writes a quick equation for for-each similar to this:
(define (for-each p l)
(if (null? l)
"done"
(p (car l)
(for-each p (cdr l)))))
Is there a specific convention for returning a side-effect from a function in Scheme, or was the "done" an arbitrary choice?
That's not really a side effect, but rather that every Scheme function must return something. The string "done" is something. Normally, when you call for-each you might do something like:
(for-each (lambda (x) (display x)) lst)
and ignore the return value from for-each. The author could have just as easily chosen any other value to return from the base case.
I'm writing a function for a CLOS class that reverses the list element of an object of said class.
I have a method that will return the reverse list, but how do I make it set the object's list to that list? Can I have a instance variable in the function that stores the list then set the element to that? Or is there an easier way?
Here's the method as it is now:
(defun my-reverse (lst)
(cond ((null lst) ‘())
(t (append (my-reverse (cdr lst)) (car lst)))))
The object it is passed is (l my-list) and the accessor would then be (my-list-ls l).
Edit: Realized that cons doesn't work on 2 lists.
Edit2: What I assume the right code would be:
(defun my-reverse (l my-list)
(cond ((null (my-list-ls l) ‘())
(t (setf (my-list-ls l) (append (my-reverse (cdr (my-list-ls l)))
(car (my-list-ls l)))))))
If you want to modify an object's slot, you need to pass that object itself to your function, not just the value of the slot you want to change.
EDIT: regarding the edit2 of the question
I assume my-list is the name of the class, and you don't actually want to pass it to the function, right? In that case, you should substitute the defun with a defmethod. Also, it should be better to change the instance only once, after you reversed the whole list, instead of at each step. You could use an inner function for that:
(defmethod my-reverse ((l my-list))
(labels ((inner (list acc)
(if (endp list)
acc
(inner (rest list) (cons (first list) acc)))))
(setf (my-list-ls l) (inner (my-list-ls l) ()))))
EDIT 2: detailed explanation
defmethod is the alternative to defun for defining (polymorphic) methods. Though, if you don't need polymorphism, you could just use (defun my-reverse (l) for the first line.
labels is for inner function definitions. Here, it defines an inner function named inner with the two parameters list and acc. inner is the function that does the actual reversing, and it's a tail-recursive function because reversing goes naturally with tail-recursion. (It can build its result with cons and is therefore of linear complexity, whereas your solution needs append and thereby is of quadratic complexity, because cons itself is constant, but append is linear.)
first and rest are just alternate names for car and cdr, endp is mostly just an alternate name for null, with the difference that endp will signal an error if its argument isn't actually a list.
Finally, the last line calls inner with the original and an empty list as arguments, and assigns the result to the slot (aka instance variable).
I have a function that takes a list that either has two or three elements.
;; expecting either ((a b c) d) or ((a b c) d e)
(define (has-third-item ls)
(if (null? (caddr ls))
false
true)
)
But this code fails with
mcar: expects argument of type <mutable-pair>; given ()
on the (null? (caddr ls)) expression.
I also tried
(eq? '() (caddr ls))
but it didn't work either. How do I tell if there's a third item or not?
You don't want caddr, you want (if (null? (cddr ls)) ... Or just use length to find the length of the list, and compare it to the value you're interested in.
The '() that terminates a list will always be in the cdr position of a pair, so looking for it in the car position (which cad+r will do) isn't going to be productive.
The problem is that if you have a list with two or fewer items, you can't take the caddr of it. Try this:
(define (has-third-item lst)
(<= 3 (length lst)))
There could be some cases where taking the length of the list can be inefficient (such as the list containing millions of items); in this case, we can test to see if the list has length zero, one, or two by hand:
(define (has-third-item lst)
(not (or (null? lst)
(null? (cdr lst))
(null? (cddr lst)))))
edit: Regarding the two other answers, while taking the cddr may work in this case as the input domain consists of list with either two or three elements, has-third-item would still fail for lists with zero or one. In the interest of generality, I suggest going with a solution that works for any domain.
Provided you know your list has either two or three elements (as you say it has), you can do
(define (has-third-item? l)
(not (null? (cddr l))))
You're checking whether the second cons cell (cddr l) has a cdr or not. You don't have to check whether l itself is null or l has only one element, unless you want a more generic function.
try...
(and l (cdr l)(cddr l))
Why not use (third ls)
Will return the third element or NIL if none is present.