Ormap version in "Realm Of Racket" - unit-testing

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.

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.

Gathering elements in range of Min and Max values from a list in Scheme

I am new to Scheme and not currently using (Racket version), therefore I do not have such built in functions as filter and etc.
My task for now is to get elements out of my inputted list, and take out of it only those that are above my MinValue and below my MaxValue
In my "lst" variable for example I have (2 4 1 6 5 4 7 3)
In my "MinValue" I have 2
In my MaxValue I have 5
So that now after I apply something similar like
(remove (< # minVal) lst)
It technically should give remove and left out:
(2 4 4 3)
But I am getting the error:
READ from #<INPUT CONCATENATED-STREAM #<INPUT STRING-INPUT-STREAM> #<IO TERMINAL-STREAM>>: objects printed as # in view of *PRINT-LEVEL* cannot be read back in
Main questions:
Does Scheme has a specific defined variable like # that is iterating through the list when remove/remove-if functions are used, so I can use it?
Is there is a way to get this to work in such way:
(remove (< # minVal) lst)
Thanks!
tag "homework" should be there, but I cannot create it yet
Almost any Scheme I know of includes a filter procedure, it's not specific to Racket, you should be able to use it (remove is not the right tool for this job).
Simply pass a lambda that receives each element in turn and you can set any condition for determining which elements go in the output list:
(filter (lambda (e) (and (>= e 2) (< e 5)))
'(2 4 1 6 5 4 7 3))
=> '(2 4 4 3)
There is no # variable that iterates through a list and gives you each element in turn, to do that you have to explicitly traverse the list using recursion, or use one of the built-in procedures that expect a list and a lambda - the lambda's parameter represents each of the elements.
If for some reason you are not allowed to use filter, it's easy to implement it from scratch, and again notice that we don't need to use remove, and that pred gets called with each of the elements:
(define (filter pred lst)
(cond ((null? lst) '())
((pred (car lst))
(cons (car lst) (filter pred (cdr lst))))
(else (filter pred (cdr lst)))))

Recursively append the first element of the list to the rest of a list

I am quite new to scheme and I want to take a list such as (1 2 3 4) and send it to a function that will return (4 1 2 3). A second run would return (3 4 1 2) and so on creating a right shifted list with each call to the function.
The first way I figured out to solve this problem is to recursively swap the first and last values of the list. So in scheme I would append the car of the list with the cdr of the list and send the cdr of the list back to my function recursively until only one last swap can be made.
However I am not great with creating recursive functions and I'm having trouble doing it in a new language for me such as scheme. This is what I have tried so far to give an idea of where I want to head.
(define (rShift lst)
(if (null? lst)
'()
(append (cdr lst (car lst))(rShift (cdr lst)))))
The best you can do is take a look at the documentation of your interpreter to see what list functions are available, and construct a solution using them. For example, in Racket using the list procedures will accomplish a straightforward solution:
(define (rShift lst)
(cons ; stick together the solution
(last lst) ; pick the last item
(take lst (sub1 (length lst))))) ; pick all items except the last one
Let's give it a try:
(rShift '(1 2 3 4))
=> '(4 1 2 3)
(rShift (rShift '(1 2 3 4)))
=> '(3 4 1 2)
There are countless ways to solve this problem, I'll leave it to you to find the one that best suits your needs, but remember - always try to solve a problem in terms of the building blocks already at your disposal, and don't reinvent the wheel. Just for fun, here's another way, using reverse:
(define (rShift lst)
(let ((rev (reverse lst)))
(cons (car rev)
(reverse (cdr rev)))))
If you are intent on doing a recursive solution, then you need to ask yourself "what part of the problem can a solve that leaves an identical but smaller part of the problem remaining" and "how do I end the recursion".
For your problem you end the recursion when you have the last element which you then use to add to the front of the list. The problem is that recursing with 'right-shift' can't be sufficient because you need to keep around the list in order to put the last element on its front.
So:
(define (right-shift list)
(if (null? list)
'()
(let shifting ((list list) (result '()))
(if (null? (cdr list))
(cons (car list) (reverse result))
(shifting (cdr list) (cons (car list) result))))))
;; Hey look, it compiles... gosh I love interactive languages.
;; ... and works.
> (right-shift '(1 2 3 4))
(4 1 2 3)
> (right-shift (right-shift '(1 2 3 4)))
(3 4 1 2)

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".

Adding an element to List in Scheme

Below is my code which takes a car element of a list(carVal) and an list(initialized to empty) as parameters. I want to append the element to the list but the same is not working.
(define populateValues
(lambda (carVal currVal)
(append currVal(list carVal ))
(display currVal)))
The display shows empty list all the time () . Can anyone help me understand why?
Well, there is append! as a primitive, which solves most of your problems, as noted already, Scheme tends to frown on mutation, it is possible, but typically avoided, so all procedures that mutate have a ! (called a bang) at their end.
Also, set! does not mutate data, it changes an environment, it makes a variable point to another thing, the original data is left unchanged.
Mutating data in Scheme is quite cumbersome, but, to give you my own implementation of append! to see how it is done:
(define (append! lst . lsts)
(if (not (null? lsts))
(if (null? (cdr lst))
(begin
(set-cdr! lst (car lsts))
(apply append! (car lsts) (cdr lsts)))
(apply append! (cdr lst) lsts))))
Note the use of set-cdr!, which is a true mutator, it only works on pairs, it mutates data in memory, unlike `set!'. If a pair is passed to a function and mutated with set-cdr! or set-car!, it is mutated every-where in the program.
This obeys the SRFI append! spec which says that it should be variadic and that it should return an undefined value, for instance.
(define l1 (list 1 2 3 4))
(define l2 (list 2 3 4))
(define l3 (list 3 1))
(append! l1 l2 l3)
l1
l2
l3
Which displays:
(1 2 3 4 2 3 4 3 1)
(2 3 4 3 1)
(3 1)
As visible, append! can take an infinite number of arguments and it mutates them all but the last.
Scheme might not be the ideal language for you though. The use of append! as said before is nonstandard, instead, append is preferred, which does not mutate and is called for its return value. Which I implement as such:
(define (append . lsts)
(cond
((null? lsts) '())
((null? (car lsts)) (apply append (cdr lsts)))
(else (cons (caar lsts) (apply append (cdar lsts) (cdr lsts))))))
> (append (list 1 2 3) (list 4 5 6) (list 'granny 'porn))
(1 2 3 4 5 6 granny porn)
Which shows a more familiar Scheme style in the absence of mutation, heavy use of recursion
and no use of sequencing.
Edit: If you just want to add some elements to a list and not per se join two though:
(define (extend l . xs)
(if (null? l)
xs
(cons (car l) (apply extend (cdr l) xs))))
(define (extend! l . xs)
(if (null? (cdr l))
(set-cdr! l xs)
(apply extend! (cdr l) xs)))
(extend '(0 1 2 3) 4 5 6)
(define list1 '(0 1 2 3))
(extend! list1 4 5 6)
list1
Which does what you expect
append creates a new list, it does not modify an existing one.
This is because in general, Scheme (and Racket in this case) is a language that prefers functional style.
You could get somewhat closer with a set! -- but even that will disappoint you since it will modify only the local binding.
Note that in Racket in particular, lists are immutable, so there's nothing that can change a list.
Furthermore, even if you could modify a list this way, it's a very inefficient way to accumulate long lists, since you have to repeatedly scan the whole list.
Finally, if you have issues at this level, then I strongly recommend going over HtDP
(append foo bar) returns the concatenation of foo and bar. It doesn't change either foo or bar.
You have to update the value of currVal with set!. Your example should have
(set! currVal (append currVal (list carVal))
(display currVal)
You really need to think about what exact functionality you are looking for
If you want to mutate a referenced list in place, then you have to do the equivalent of append! (as noted in the other answers). But that is dangerous, BECAUSE you may have other code that is counting on the list being immutable, and if you are going to do that, your procedure needs to have a ! in the end to flag that danger.
A cheap approximation to what you want to do, in a more functional style, is:
(define (populateValues carVal currVal)
(let ((ll (append currVal (list carVal))))
(display ll)
ll))
Note that it makes a new list, does the append, displays the result, and RETURNS the new list as a value. This is a useful debugging technique if you don't have access to the intermediate value: bind to a varible, display or log it, and then return it.