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)
Related
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))
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
I'm new to Lisp and I'm having trouble figuring out how I add a list to another list. I start with an empty list, and I have to add new lists, each containing three elements. For example,
(add '(1 2 3) '())
would return ((1 2 3)) [let's call it new-list], and adding a new list to this new one, for example
(add '(4 5 6) new-list)
would return ((1 2 3) (4 5 6)) or ((4 5 6) (1 2 3))
I've tried a few different ways, but so far the closest I've come up was ((((1 2 3)) (4 5 6)) (7 8 9))
I was using something like this:
(defun add (lst new-let)
(if (null lst) '()
(setf new-lst (cons new-lst (cons lst '()))))
Have you tried :
(defun add (thing lst) (append lst (list thing)))
I haven't tried this with Common Lisp as I am more of a Scheme kind of guy, bu I think it would work.
The way I read it, your requirement is exactly cons (non destructive) or push (destructive).
You being new to LISP I'd like to give you an alternative to the accepted answer.
Lists are singly linked list chains. Such structure allows for adding and removing in front to be a constant time operation while adding or removing something from the end would take as many turns as there are elements in the list in both time and space (it will have to recreate the list structure on it's way).
(defun add (element list)
(cons element list))
This looks very familiar.. It's actually just a wrapper to cons. So lets imagine you have a practical application where you'd like to use add, but needed the elements in the order in your question. One way to do it would then be to finish up first (add whats to add), then do one reverse or nreverse (if every element was made in your function and mutation won't matter for the outside)..
(defun fetch-all (num-elements thunk &optional acc)
(if (zerop num-elements)
(nreverse acc)
(fetch-all (- num-elements 1) thunk (add (funcall thunk) acc)))); add == cons
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.
I have defined a list (in Racket/Scheme):
(define myList (cons 'data1 (cons 'data2 (cons 'data3 (cons 'data4 empty)))))
or
(list 'data1 'data2 'data3 'data4)
And I want to write a function that cycles through the list and outputs all values of the list.
(define (outputListData list)
(cond
[(null? list) list]
[else (getListData)]))
With what function can I cycle through the content of the list? I know one can use first & rest to get list data, but I guess that's not the right way here.
BTW: Is there a good, compact racket reference like php.net? I find the official Racket docs very confusing ...
You can use a for loop. Example:
(for ([x (list 1 2 3)])
(printf "~s -> ~s\n" x (* x x)))
There are more functional ways to do this, of course, but this way works too. You'll probably want to look at a textbook like How To Design Programs to do the recursive approach. See: http://www.ccs.neu.edu/home/matthias/HtDP2e/
dyoo's solution is nice and succinct in a Scheme like Racket that has useful iteration routines built in. Just FYI, though, your 'outputListData' is not far from being the standard recursive way to do this. You just need to change a couple of lines:
(define (outputListData list)
(cond
[(null? list) #f] ; actually doesn't really matter what we return
[else (printf "~s\n" (first list)) ; display the first item ...
(outputListData (rest list))])) ; and start over with the rest
Since this is an "imperative" kind of procedure that isn't designed to return a value, it doesn't really matter what we do with an empty list so long as we stop recurring (to avoid an infinite loop). If the list isn't empty, we output the first element and start over recursively with the rest of the list.
BTW, here's another way you could write something almost identical if you just needed a "for" loop in the middle of some other function:
(let loop ((l (list 'foo 'bar 'baz 'quux))) ; or put whatever input you need
(cond ((null? l) #f)
(else
(printf "~s\n" (first l))
(loop (rest l)))))
One way to think about this "named let" is that it defines a temporary function called loop, which works just like outputListData above. Scheme has the nice property that it won't grow the stack for "tail calls" like these, so you can always write what would be an "iterative" for or while loop in this recursive style.
I highly recommend The Little Schemer by Friedman and Felleisen for a quick intro to this style of function writing! I found it through Douglas Crockford's page here.
Edit as per comments: Use for-each
(for-each display myList)
Try this:
(void (map display myList))
Breaking it down:
(void x) causes x to be ignored instead of returned to the REPL/parent expression as a value.
(map function lst): For a list '(a1 a2 ... an) returns the list '((function a1) (function a2) ... (function an)).
So we use map to display all the items, but since we only care about the side-effect and not the return value, we call void on the returned list.
Official docs:
void
map
I think the solution that is the easiest to understand it to come up with a so called "list-eater" function. This is the way my university introduced recursion and lists in Racket. Also most books on Racket (i.e. "How To Design Programs" or "Realm Of Racket") explain it this way. This is the code:
(define my-list (list 'data1 'data2 'data3 'data4))
(define (print-list a-list-of-data)
(when (not (empty? a-list-of-data))
(print (first a-list-of-data))
(print-list (rest a-list-of-data))))
If you call the function with the example list my-list, you will get the following output:
(print-list my-list)
'data1'data2'data3'data4
The function does the following: As long as the given list is not empty, it grabs the first element of that list and passes it to the function print. Then, it tells itself to do the exact same thing with the rest of the list. (It calls itself on the rest of the list.) This second part is what they call recursion.
However, you can shorten that by using a function called map:
(define (print-list a-list-of-data)
(map print a-list-of-data))
This basically says that you want the function print to be called on each element of the given list. The output is exactly the same.
Hope it helped!