Why doesn't DrRacket recognize butlast? - list

I was told butlast return all items in the list except the last item.
Here's a picture of my output when I try entering it manually:
The output was supposed to be '(1 2) because we removed the last item from the list.I found a documentation online on butlast but I'm not sure why the command isnt working for me: https://planet.racket-lang.org/package-source/cce/dracula.plt/6/0/planet-docs/manual/Lists.html#(def._((planet.dracula..scm.(cce._dracula..plt._6._0)._language)._butlast))

The documentation you have referenced belongs to the ACL2 programming language, where butlast is a well defined built-in procedure.
Racket, however, does not have a built-in procedure named butlast. You can verify this using Racket's official documentation, which can be found at: https://docs.racket-lang.org/. This is why you are getting the error butlast: undefined; when applying the function, because the procedure is neither built-in nor one that you have defined.
In Racket, the built-in drop-right procedure exists and works the same way as butlast. For example:
(drop-right '(1 2 3) 1)
=> '(1 2)
(drop-right '(1 2 3) 2)
=> '(1)
You can also manually create a butlast procedure as follows:
(define (butlast lst n)
(let ([len (length lst)])
(if (< len n)
"handle error"
(take lst (- len n)))))
For example:
(butlast '(1 2 3) 1)
=> '(1 2)
(butlast '(1 2 3) 2)
=> '(1)

Related

Resources for Learning Box and Pointer Diagrams

I am currently working my way through Berkely's summer 2011 CS3L course and am struggling to understand Box and Pointer Diagrams. How to build them and how to interpret them.
The instructions provided are here.
However, I am still not "getting it."
I understand that lists are combinations of pairs and that the cdr of a pair may point to another pair. I also understand that the pair that the cdr points to may be another list. I just don't understand how to draw it all out in a diagram.
For reference, here is an example of a problem I am being given is:
(define cal
(list (append (list (cons (list 1 2) (cons 3 '())))
(list (cons 4 (cons 5 '()))))
6
7))
Given a code like the one above, I am suppose to draw the box and pointer diagram and then be able to say what combination of car and cdr is necessary to get any given number in the list.
Again, for reference, below is the diagram I should have been able to come up with:
To reiterate, what I'm looking for is a video or article that may explain the building of box and pointer diagrams more clearly.
Thank you in advance for anyone willing to point me in the right direction.
[Note that this answer is not encouraging you to cheat: if you are doing a course which requires you to be able to draw box & pointer diagrams then you should be able to do that, not have a program do it for you. But the program can help you learn.]
One good approach to learning how box & pointer diagrams work is to be able to talk to a program which knows how to draw them. In Lisp's long ago golden age we had wonderful conversational interfaces on our Lisp machines which let graphics and text be intermingled, along with nice graph-drawing programs from which tools could easily be built to do this. Using such tools you could construct various structures out of conses and get the program to draw diagrams for you, and thus you got a good handle on how the structures work.
Well ... it turns out Lisp's golden age is now. If you use Racket (and you can use Racket if you are not already using it) then there is a very wonderful package called sdraw which does this. It's not bundled with the Racket distribution, but to install it you can either use DrRacket's package manager or just do
raco pkg install --auto sdraw
which will install it. Now you can (in a DrRacket window, this won't work in a terminal session) simply talk to the Racket REPL and get it to draw cons trees for you:
By simply interacting with the language and letting it draw things for you then you can get a really good feel for how the various structures hang together.
This answer uses Common Lisp for its examples, but it is not fundamentally different in Scheme. Note also that you can play with sdraw.lisp in Common Lisp (e.g. with CCL or SBCL programs) if you want to see how printing the diagram can actually be implemented.
You first have to be clear about the result you want to print, which might be difficult when the source contains cons/list/append operations. Also, since the source code is also a tree of cons-cells, you have to take care not to mix the source with the value obtained after its evaluation.
So it all starts with evaluating the form correctly.
Evaluate cal
Let's first evaluate the expression. Below, I also mention drawing the boxes directly from the input expression, but IMO it helps to detail that intermediate step.
The result is the same in Scheme and Common Lisp, after recursively evaluating all expressions:
((((1 2) 3) (4 5)) 6 7)
Here is how you could ask the system to trace the computation, in Common Lisp. First of all, know that you cannot trace standard functions like list, etc. So let's shadow them in a custom package with simple wrappers:
(defpackage :so
(:use :cl)
(:shadow #:list #:cons #:append))
(in-package :so)
(defun list (&rest args) (apply #'cl:list args))
(defun cons (&rest args) (apply #'cl:cons args))
(defun append (&rest args) (apply #'cl:append args))
Then, in the REPL, go to that package:
CL-USER> (in-package :so)
#<PACKAGE "SO">
Ask to trace those functions:
SO> (trace list append cons) ;; the shadowing ones
(LIST CONS APPEND)
Now, you can enter the value of cal directly, but this time the symbols being used are the one we asked to trace.
SO> (list (append (list (cons (list 1 2) (cons 3 '())))
(list (cons 4 (cons 5 '()))))
6
7)
The environment then evaluates the form and prints how each function is called and what results it returns.
0: (SO::LIST 1 2)
0: LIST returned (1 2)
0: (SO::CONS 3 NIL)
0: CONS returned (3)
0: (SO::CONS (1 2) (3))
0: CONS returned ((1 2) 3)
0: (SO::LIST ((1 2) 3))
0: LIST returned (((1 2) 3))
0: (SO::CONS 5 NIL)
0: CONS returned (5)
0: (SO::CONS 4 (5))
0: CONS returned (4 5)
0: (SO::LIST (4 5))
0: LIST returned ((4 5))
0: (SO::APPEND (((1 2) 3)) ((4 5)))
0: APPEND returned (((1 2) 3) (4 5))
0: (SO::LIST (((1 2) 3) (4 5)) 6 7)
0: LIST returned ((((1 2) 3) (4 5)) 6 7)
((((1 2) 3) (4 5)) 6 7)
Vizualize as cons cells
It can be helpful to view lists as chains of cons-cells, i.e. turn (a b c) into (a . (b . (c . nil))). Let's define a helper function:
(defun consprint (x)
(if (consp x)
(format nil
"(~a . ~a)"
(consprint (car x))
(consprint (cdr x)))
(prin1-to-string x)))
Here is the result:
SO> (consprint '((((1 2) 3) (4 5)) 6 7))
"((((1 . (2 . NIL)) . (3 . NIL)) . ((4 . (5 . NIL)) . NIL)) . (6 . (7 . NIL)))"
Draw: a term rewriting approach
Use a recursive, bottom-up approach to draw it.
Definition.: Here I define a leaf as a cons-cell that has atoms in both its CAR and its CDR slots: e.g. (0 . NIL) and (X . Y) are both leaves, but not ((0 . 1) . 2). Note that this includes improper lists, something I am relying on to explain the drawing method when I replace subterms by symbols.
((((1 . (2 . NIL)) . (3 . NIL)) . ((4 . (5 . NIL)) . NIL)) . (6 . (7 . NIL)))
^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^
Above I underlined all leaves: you can easily draw those boxes, and label them with symbols (A, B, ...).
Here below I replace the original cells with the names of their associated boxes, and again underline the new leaves:
((((1 . A) . B) . ((4 . C) . NIL)) . (6 . D))
^^^^^^^ ^^^^^^^ ^^^^^^^
Then, when there is a symbol representing a box, draw an arrow to that box. For example, you define a box named E that corresponds to (1 . A), so you draw [1/x] and connect the x to box A.
You obtain:
(((E . B) . (F . NIL)) . G)
Now, consider (E . B): its car is a symbol, so the box you need to draw has no value, but an outgoing arrow from the CAR slot that points to the E cell (just like its CDR points to B).
You repeat this process until termination. The rest is visual layout, where typically boxes that are just linked lists of atoms are laid out horizontally.
Directly drawing from expressions
Presumably the original exercise wants you to draw boxes right from the original expression. The same can be done as above, working upward from leaf expressions and replacing their values by symbols denoting existing boxes.
A cons maps directly to a box.
a list is just a repeated application of cons, and you can go quickly by drawing as many boxes as there are elements.
append in practice makes a copy of all but the last list in arguments, but when drawing you can "mutate" the existing boxes. For each existing box, keep following the CDR until you reach a box with no arrow in cdr, and link that box to the next one in the arguments, thus chaining the different boxes together.
It can be interesting to also draw the actual, purely functional version of append to see how structure sharing and garbage collection work.
Starting from the code, you can work from the top level down. Given:
(define cal
(list (append (list (cons (list 1 2) (cons 3 '())))
(list (cons 4 (cons 5 '()))))
6
7))
you can see that the first level is a list containing three elements: a complex object, a 6, and a 7. This can be represented by three cons cells:
Now you just need to figure out what the car of the first cons cell points to. Looking back at the code, this points to a list that is comprised of two lists, appended together. If you look at the parentheses, you can see that the first call to list is taking only one argument, so this will create a list containing one element.
When two lists are appended, the nil that closes the first list is replaced by a pointer to the front of the second list so:
The first list of the two to be appended is created by this code:
(list (cons (list 1 2) (cons 3 '())))
Here, the list (1 2) is consed to the front of the list (3) to create a new list. This is a list of two elements where the car of the list points to the list (1 2) and the cdr of the list is (3). We can go ahead and draw the boxes for this layer:
And since the car of the last layer just points to the list (1 2), we can fill that in:
Now, the second argument to the append function is also a list containing only one element, so:
That single element is the result of (cons 4 (cons 5 '())), which is just the list (4 5), so we can finally finish our box diagram by pointing to this list from the car of the last cons cell:
Try starting from the inside out, just as the interpreter will. Draw the diagram for, say, (cons 3 '()) - pretty simple, right? Now, should anything point to it? Yes, it is the cdr of (cons (list 1 2) (cons 3 '())). So, when you draw the diagram for that larger expression, make sure its cdr points to the first sub-diagram you drew. To finish drawing this larger expression, you'll also need to draw a diagram for (list 1 2) - just as easy as where you started.
Work your way outwards from there - the append operation is the trickiest part, but the instructions you linked explained how append works.
Forget lists. There are no lists. There are only pairs.
(define cal
(list (append (list (cons (list 1 2) (cons 3 '())))
(list (cons 4 (cons 5 '()))))
6
7))
=
(define NIL '())
(define A (cons 1 (cons 2 NIL))) ; (list 1 2)
(define B (cons 3 NIL)) ; (cons 3 '())
(define C (cons 5 NIL)) ; (cons 5 '())
(define cal
(list (append (list (cons A B))
(list (cons 4 C)))
6
7))
=
(define NIL '())
(define A (cons 1 (cons 2 NIL)))
(define B (cons 3 NIL))
(define C (cons 5 NIL))
(define D (cons A B))
(define E (cons 4 C))
(define cal
(list (append (list D)
(list E))
6
7))
=
(define NIL '())
(define A (cons 1 (cons 2 NIL)))
(define B (cons 3 NIL))
(define C (cons 5 NIL))
(define D (cons A B))
(define E (cons 4 C))
(define F (list D E)) ; (append (list D) (list E))
(define cal
(list F
6
7))
=
(define NIL '())
(define A (cons 1 (cons 2 NIL)))
(define B (cons 3 NIL))
(define C (cons 5 NIL))
(define D (cons A B))
(define E (cons 4 C))
(define F (cons D (cons E NIL))) ; (list D E)
(define cal
(cons F
(cons 6
(cons 7 NIL))))
Each cons is a box. Each name is a pointer.
And that's all.

Clojure: how to convert cons to list

(cons 1 (list 2 3)) returns a clojure.lang.cons. How can I convert it to clojure.lang.PersistentList?
Instead of calling cons and trying to convert the result, use conj:
(conj (list 2 3) 1)
=> (1 2 3)
(type (conj (list 2 3) 1))
=> clojure.lang.PersistentList
Clojure: how to convert cons to list
Don't!
Clojure is built upon extensible abstractions. One of the most important is the sequence.
I can think of no reason why you would want to convert a cons into a listor vice versa. They are both sequences and nothing much else. What you can do with one you can do with the other.
The above takes forward Leetwinski's comment on the question.
You can apply the contents of the returned sequence to the list function:
(apply list (cons 1 (list 2 3)))
=> (1 2 3)
(type *1)
=> clojure.lang.PersistentList
The easiest way would be to turn it into a vector. This data type works great in Clojure. In fact, when programming in Clojure, the most of the data is kept either in vectors or maps while lists are used for "code as data" (macro system).
In your case, the solution would be:
user=> (vec (cons 1 (list 2 3)))
[1 2 3]
I don't know such a case where you need a list exactly, not a vector or a seq. Because most of the functions operate on sequences but not strict collection types. The cons type should also work, I believe.
If you really need a list, you may use into function that is to convert collections' types. But please keep in mind that when dealing with a list, the order will be opposite:
user=> (into '() (cons 1 (list 2 3)))
(3 2 1)
So you need to reverse the input data first:
user=> (into '() (reverse (cons 1 (list 2 3))))
(1 2 3)
user=> (type (into '() (reverse (cons 1 (list 2 3)))))
clojure.lang.PersistentList

Ormap version in "Realm Of Racket"

In "Realm of Racket", the authors build a built-in function for educational purposes.
Their implementation of ormap is:
(define (my-ormap-book pred lst)
(cond [(empty? lst) #f]
[else (or (pred (first lst))
(my-ormap-book pred (rest lst)))]))
This code seems to work fine in many cases, like the unit-tests bellow show:
(require rackunit)
(check-equal? (my-ormap-book add1 '(3 4 5)) 4)
(check-equal? (my-ormap-book add1 '()) #f)
(check-equal? (my-ormap-book positive? '(1 2 a)) #t)
However, the real Ormap, like racket documentation shows - link - also works with two or more lists as inputs, like:
(check-equal? (ormap + '(1 2 3) '(4 5 6)) 5)
When doing that test with "Realm of Racket"s implementation, you get:
(check-equal? (my-ormap-book + '(1 2 3) '(4 5 6)) 5)
my-ormap-book: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 3
arguments...:
How do I solve this?
How do I make the "my-ormap-book" procedure pass on this test case?
You're right that the built-in ormap handles multiple lists. I think I would separate your question into two questions. First: how do you define a function that takes a variable number of arguments (known as 'variadic')? Second: how do you define a variadic ormap?
In answer to the first: there are a couple of ways of defining variadic functions. The simplest is to use a dot in the argument list, before the last argument:
(define (f a b . rest-args)
(first rest-args))
All arguments after the first two are bundled into a list with the given name.
This totally useless function accepts two or more arguments, and returns the third one (okay, pointless and broken).
In answer to your other question... well, this is a question of simultaneous recursion over multiple lists of the same length, and I think I'd refer you to section 23.1 of HtDP 2e.

Putting a list in a parameter in scheme

So I am new to using Scheme/Guile and have an assignment where I must take 2 inputs; a simple variable and a list.
I then add the variable to each number in the list and print it out. I have got it to load but when I enter this:
(add 1 (1 2 3))
I get this error:
Backtrace:
39: 0* [add 1 ...
39: 1* [1 2 3]
standard inout:39:8: In expression (1 2 3):
standard input:39:8:wrong type to appy: 1
ABORT: (misc-error)
Here is the code that I currently have.
(define a (list a))
(define (add y a)
(define x 0)
(while (< x (length a))
(display (+ y (car a)))
(newline)
(set! a (cdr a))
(set! x (+ x 1))
)
)
My question is:
How do I get the list to work in the parameter? I have looked around online but havent found much to fix this problem.
Many thanks ahead of time for any help you can give me.
You're getting an error because (1 2 3) tells it to call the function 1 with two arguments, 2 and 3. To create a list containing 1, 2 and 3, use (list 1 2 3).
Do you really intend to write a procedure in such an imperative way? It looks not very Scheme-like. Evaluating your procedures in GNU Guile yields many error messages about unbound variables etc. set! is eval for beginners of Scheme ;) :) (SICP treats assignment extensively in chapter 3). You can do it much easier in functional style without the side-effects of set! and display.
If you are already aware about mapping and high-order functions, you could do something like this:
(define (add x)
(lambda (y) (+ x y)))
(map (add 1) (list 1 2 3))
===> (2 3 4)
If not, write a recursive procedure yourself:
(define (add-to-list x list)
(if (null? list)
'()
(cons (+ x (car list))
(add-to-list x (cdr list)))))
(add-to-list 1 '(1 2 3))
===> (2 3 4)
In order to learn thinking recursively, consult books like SICP, HTDP or "The litte Schemer".

How to get a PersistentList from a Cons?

I am loading forms from a file using slurp, read, and cons'ing them together to recursively read all forms into a collection. Then wish to pass this into scriptjure's (js [& forms]) function, which expects a (list?), but (cons) gives me a Cons classed-object. How may I convert (class (cons 1 '(2 3 4 5))) to be IPersistentList? Thanks!
Use (apply list x) to create a list from sequence x :
user=> (class (apply list (cons 1 '(2 3 4 5 6))))
clojure.lang.PersistentList
Alternatively, if you start with a list and then conj forms onto it, you'll end up with a list:
user=> (class (conj (list 1 2 3) 4))
clojure.lang.PersistentList
No need for cons in this case since conj, given a list, returns a list.