What's the point of building a list with a non-list tail? - list

The Emacs lisp manual states about the function nconc that:
Since the last argument of nconc is not itself modified, it is reasonable to use a constant list, such as '(4 5), as in the above example. For the same reason, the last argument need not be a list
And indeed I can write
(setq x '(1 2 3))
=> (1 2 3)
(nconc x 0)
=> (1 2 3 . 0)
but that yields a totally broken list:
(length x)
=> eval: Wrong type argument: listp, 0
(butlast x)
=> butlast: Wrong type argument: listp, 0
How can I retrieve the original list? (reverse (cdr (reverse '(1 2 3 . 0)))) doesn't cut it either.
In which contexts is this a useful pattern? In the standard distribution some functions in minibuffer.el use it, in particular completion-all-completions and the like.

They're not "broken" lists; they're actually known as improper lists (as opposed to nil-terminated lists, which are proper lists). Many list functions, such as length and butlast that you just named, expect proper lists, and listp returns true only for proper lists.
Improper lists are used in association lists (where the associations are often not proper; though the alist itself must be proper).
If you want to make an improper list proper, you have two options:
Remove the "improper" element.
Treat the improper element as the last element of the proper list.
Here's a procedure I wrote called properise which will do the former:
(defun properise (x)
(let ((r nil))
(while (consp x)
(push (pop x) r))
(nreverse r)))
(If you want the latter behaviour, add (unless (null x) (push x r)) just before the nreverse line.)

Generally I would avoid creating data structures like that, where the last element is a cons cell with some object other than NIL in the cdr... It makes debugging harder, it's a hack, makes code more difficult to understand, ...

I'm still unsure why this is a good pattern, but here's an easy way of getting a proper list out of an improper one, without making a copy:
(defun nmake-proper-list (x)
(let ((y (last x)))
(setcdr y nil)
x))

Related

Scheme - Testing if argument is a list (proper or improper)

I'm very new to scheme and am trying to figure out how to define a function that tests if the parameter to that function is a list, where being a proper list doesn't matter.
I've discerned that I need to check if the argument is either the empty list or a pair. I have the empty list case working fine, but I'm not sure how to check for the pair. I'm just coming off working with prolog, so my initial thought was to do something like this:
(define list?
(lambda (ls)
(if (or (eq? ls (quote()))
(cons(car(ls) cdr(ls))))
true false)))
My thinking was that if scheme could car and cdr the parameter, then it must be a pair, and it would return true. Otherwise it would just fail.
However, passing the argument '(1 2) yields this result:
(list? '(1 2))
. . application: not a procedure;
expected a procedure that can be applied to arguments
given: (1 2)
arguments...: [none]
I don't really understand what's going on here. Additionally, I feel like my thinking as to how to make this function is flawed, but I don't really know how to correct it.
EDIT: Is the issue that (if .....) is looking for a boolean from cons?
You have right idea! But the main reason why your code is not working is that on fourth line you have wrong brackets. This is right transcription of your code:
(define list?
(lambda (ls)
(if (or (eq? ls (quote()))
(cons (car ls) (cdr ls)))
#t #f)))
But in my opinion this solution is bad for these reasons:
If you supply improper list to this procedure it will end by an error when trying to do car or cdr.
For example: (1 2 3 . 4) will end by an error.
In Scheme you have to use literals #t and #f to denote true and false.
Cons always end by "true"
It will not check entire list.
I would write that procedure like this:
(define list?
(lambda (ls)
(if (null? ls)
#t
(and (pair? ls)
(list? (cdr ls))))))
Lets try this on an example: (3 . 4). It is just pair - not a list.
The ls is (3 . 4). Is it null? No, then continue to second if branch.
Is it pair? Yes - continue in and and recursively call list? with 4
The ls is 4. Is it null? No. Again, continue to second branch.
Is it pair? No! Procedure returns #f

Building a list with loops

We just covered loops today in class and I've got a few things I need to do. Put simply, I have to build a list using loops instead of recursion. I seem to be at a stumbling block here. For this example, we need to do a simple countdown. The function takes an argument and then returns a list of all the positive integers less than or equal to the initial argument. (countdown 5) => (5 4 3 2 1)
I'm having a hard time getting loops for whatever reason. The ones we talked about was Loop, Do, Dotimes, and Dolist. I've tried this with a couple loops and always end up with a similar result.
(defun countdown (num)
(cond ((= num 0) nil)
(T (let* ((list nil))
(loop
(if (= num 0) (return list)
(setf list (cons list num)))
(setf num (- num 1)))))))
My output shows up like this:
(((((NIL . 5) . 4) . 3) . 2) .1)
update: I've solved the issue. Apparently I needed to reverse the order in the cons, so num comes before list. Does anyone care to explain this? I thought you put the list first and then what you put second would be added to the end of it. At least, that's how I've been using it so far without issue.
Reverse the arguments to cons (and why)
You wrote in an answer (that, since it asks for more information, perhaps should have been a comment):
I've solved the issue. Apparently I needed to reverse the order in the
cons, so num comes before list. Does anyone care to explain this? I
thought you put the list first and then what you put second would be
added to the end of it. At least, that's how I've been using it so far
without issue.
The function is documented in the HyperSpec clearly: Function CONS. The examples in the documentation show, e.g.,
(cons 1 (cons 2 (cons 3 (cons 4 nil)))) => (1 2 3 4)
(cons 'a (cons 'b (cons 'c '()))) => (A B C)
(cons 'a '(b c d)) => (A B C D)
and even the note
If object-2 is a list, cons can be thought of as producing a new list which is like it but has object-1 prepended.
It may help to read through 14.1.2 Conses as Lists, as well, which includes:
A list is a chain of conses in which the car of each cons is an element of the list, and the cdr of each cons is either the next link in the chain or a terminating atom.
Concerning loop
Many of the answers here are pointing out to you that the loop form includes a special iteration language. That's true, but it can also be used in the way that you're using it. That way is called a simple loop:
6.1.1.1.1 Simple Loop
A simple loop form is one that has a body containing only compound
forms. Each form is evaluated in turn from left to right. When the
last form has been evaluated, then the first form is evaluated again,
and so on, in a never-ending cycle. A simple loop form establishes an
implicit block named nil. The execution of a simple loop can be
terminated by explicitly transfering control to the implicit block
(using return or return-from) or to some exit point outside of the
block (e.g., using throw, go, or return-from).
Simple loops probably aren't as common as loops using the nicer features that loop provides, but if you just covered this in class, you might not be there yet. The other answers do provide some good examples, though.
If you speaking about common lisp loop, your countdown may look like this:
(defun countdown (from-number)
(loop :for x :from from-number :downto 1 :collect x))
CL-USER> (countdown 10)
(10 9 8 7 6 5 4 3 2 1)
Using loop, which has its own "special-purpose language" that does not really look like Lisp:
(defun countdown (n)
(loop
for i from n downto 1
collect i))
Or using do:
(defun countdown (n)
(do ((i 1 (1+ i))
(res nil (cons i res)))
((> i n) res)))
See here, especially chapters 7 and 22.

Scheme list always in reverse order

Probably a trivial question for most of the more advanced schemers here, but as a newcomer, I've found this to be a problem.
I need a way to construct a new list that is in the same order it was when it came in. As an example, say we are given a list '(1 2 0 3 4 0 0 5). But traversing the list and passing the cdr back as the 1st argument ends up constructing the new list backwards.
Here's an example in code:
I pass it an "old-list" that needs work done on it and an empty list as "new-list" to be formed and returned.
note that taking 0s out is just here as "some condition" that the new list must meet
(define (form-new-list old-list new-list)
(cond ((null? old-list) new-list)
(else
(if (eq? (car old-list) 0) (form-new-list (cdr old-list) new-list)
(form-new-list (cdr old-list) (cons (car old-list) new-list))))))
;test
(form-new-list '(1 2 0 3 4 0 0 5) '()) ; gives (5 4 3 2 1)
;but want (1 2 3 4 5)
I DO NOT just want to reverse the list that is returned with a reverse procedure, but rather, want the new list to be put together in the correct order in the first place.
Is there some kind of "trick" to this, like making the recursive call somewhere else perhaps?
Any advice is greatly appreciated.
You're looking for the natural way to traverse a list using recursion. Use this procedure as a template for your solution - it simply copies a list exactly as it is received:
(define (copy lst)
(if (null? lst)
'()
(cons (car lst)
(copy (cdr lst)))))
Notice the following points:
The recursion ends when the input list is null, and given that we're building a new list, the correct value to return is the null list
We're interested in building a new list, we do this by consing a new element for the output list, which in this case happens to be the first element of the input list (its car part)
Finally, the recursive step advances by invoking the procedure with the rest of the input list (its cdr part)
As usual, I end up my answers to people learning how to think recursively by recommending you take a look at either The Little Schemer or How to Design Programs, both books will teach you how to grok recursive processes in general, using Scheme.

Altering a list permanently in common lisp

I have a list that is used within a loop, and on each iteration I apply a function that will alter the list permanently (popping and adding elements). The problem is, the original list is never changed whenever it is nil. How may I solve this problem?. My code is shown below
(defun looping-func ()
(let ((queue '(2)))
(loop while (not (null queue)) do
(let ( (num (pop queue)))
(if (oddp num)
(format t "~%~A success" num)
(progn (format t "~%fail")
(add-to-list (1+ num) queue)))))))
(defun add-to-list (elem l)
(nconc l (list elem)))
The code works as intended if the list contains more than 1 element. if it contains exactly 1 element, once that element is popped and the list becomes nil, the applied changes aren't permanent to the list anymore. I suppose this is because of how nconc is defined, if the first argument is nil, just return the second one without any alteration. Any ideas on how to go about this?
PS: I know the code above is useless, but I am using the same concept for a school project that I unfortunately can't post code for.
Change
(add-to-list (1+ num) queue)
to
(setq queue (add-to-list (1+ num) queue))
You can't "extend" nil with nconc
(nconc nil . lists)
is equivalent to
(nconc . lists)
so, you need to put the result of add-to-list in queue
Don't add elements to the end of a list.
Never.
Lists in Lisp are designed in a way that adding an element to the head is cheap. Adding to the end is potentially costly.
To implement a LIFO queue you need a different implementation.
Don't alter constant literal data in source code during runtime.
Indent your code properly.
Because I assumed this to be an exercise, here's an example, which you shouldn't use in your daily practice, you should use push macro, which probably does something similar to it:
(defmacro push-example (item list)
(let ((the-list list)) ; we do this to prevent
; multiple evaluations
; of the `list' argument
`(setq ,the-list (cons ,item ,the-list))))
(defparameter *test* nil)
(push-example 'foo *test*) ;; (foo)
*test* ;; (foo)
While you didn't ask for a macro (you asked for the function), Doug's answer is technically more correct, this illustrates how you could have done it using code generation through macro. Notice how this is basically doing the same thing as your function does, except that it can encapsulate the call to setq you would have to make otherwise.

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)