Checking multiple outputs with one test in Racket - unit-testing

I am trying to use the library rackunit to do some tests.
However, I would like to check many outputs with a single test, like this:
#lang racket
(require rackunit)
(check-equal? (add1 1) (* 2 1) (- 3 1) (+ 2 0))
As you see, this test shall pass, since all outputs are 2.
However, this test fails, due to a syntax problem:
check-equal?: bad syntax in: (check-equal? (add1 1) (* 1 2) (- 3 1) (+ 2 0))
Is there a way to do this unique test with multiple procedures returning a value?
Looking at the documentation I could not find it.
If I am unable to do this, I think I will be repeating myself...

If you are just checking numbers, like Gibstick suggested, you can just use check-true and =. However, if you are not testing numbers, we need to get a little more creative.
If the objects you want to check equality on are transitive: (aka, if (equal? a b) and (equal? b c) than (equal? a c), you can just run check-equal? in a loop:
(define items (list 'items 'to 'check))
(define compare-item 'correct-item)
(for ([i (in-list items)])
(check-equal? i compare-item))
Of course, if the item equality is not transitive, then you will need to check every item with every other item. You can still do this with a loop, it just becomes a bit more complicated. However, generally speaking, equality testing on items is transitive.

You can use the more general check-true with =, since all of your values are numbers.
#lang racket
(require rackunit)
(check-true (= (add1 1) (* 2 1) (- 3 1) (+ 2 0)))

Related

Recursively adding to a list using Scheme

I'm brand new to functional programming, and relatively new to programming as a whole. So I'm pretty lost trying to understand the syntax of Scheme. But this is a pretty simple question. I'm trying to create a function that recursively fills and prints a list from numbers x to y. Between recursion and this being a new language for me, I'm quite stuck.
(define (gen-list x y)
(if (> start end)
'()
(append '() (gen-list ((+ 1 x) y)) ) ))
If I were to enter in (gen-list 1 5) I would expect the result to be 1 2 3 4 5. This is currently giving me an error of "application: not a procedure" when it tries to call itself again. I have gotten around the error, but not been able to print anything remotely like what I'd like to. Any help is appreciated.
You have a couple of errors:
The parameters are called x and y, but you refer to them as start and end (I'd suggest to use start and end instead, they make the code easier to understand.)
You have more parentheses than needed in the last line. This is very important and an endless source of confusion for beginners. Don't surround all expressions with () unless you want to call a procedure.
We recursively build new lists with cons, append is for concatenating existing lists.
You're not actually using start, which is the current element in the recursion, to build the new list - you're just appending empty lists.
A list is an element consed to another list, or the empty list '(). That's why we return '() in the base case. For example, this is how a two-element list looks like: (cons 1 (cons 2 '())).
With all said and done, this is the proper way to build our list:
(define (gen-list start end)
(if (> start end)
'()
(cons start
(gen-list (+ start 1) end))))
As a final comment: the above procedure already exists in Racket, you don't need to rewrite it. Read about range in the documentation.
One of the problems with the 'obvious' answer to this question is that it doesn't really work very well. Consider this:
(define (gen-list start end)
(if (> start end)
'()
(cons start
(gen-list (+ start 1) end))))
Well, if start is much less than end there are going to be a huge number of recursive calls on the stack, because this is a properly recursive function: the recursive call to gen-list is a real call and has to return before the call to cons (which is a tail call) can happen.
The way to deal with this is to turn patterns which look like (cons x (<recursive-call> ...)) into patterns which look like (<tail-call> ... (cons x ...)): you need a function with an extra argument, an accumulator. This means that the calls which were previously recursive are now tail calls and everything is therefore good: the process is now iterative.
The problem with this is that lists come out backwards (you need to think about why this is, but it's obvious after a bit of thought). So you then need to reverse the result. Fortunately reversing a list is also an iterative process, so that's OK.
But in this case, well, you can just count backwards! So a simple-minded approach looks like this, using a locally-defined auxiliary function (this can be defined as a top-level function, but why bother?):
(define (gen-list low high)
(define (gla i result)
(if (< i low)
result
(gla (- i 1) (cons i result))))
(gla high '()))
You can see this is counting backwards: the initial call to gla starts with high & then constructs the list backwards. So, now:
> (gen-list 1 3)
'(1 2 3)
As we want.
This is such a common pattern in Scheme that there is a special construct for it: named let. So we can rewrite the above more idiomatically as:
(define (gen-list low high)
(let gla ([i high] [result '()])
(if (< i low)
result
(gla (- i 1) (cons i result)))))
This is exactly the same as the previous answer: it just moves the initial call to the top and combines it with the local definition of gla. This is probably the idiomatic Scheme way to do something like this (although people who write more Scheme than me might differ: I'm really a CL person and have inevitably poor taste).
This is where the story should end, but I can't resist adding the following. In the bad old days of comp.lang.lisp, people used to ask obvious homework questions and since there was no karma system one approach was to give an answer which solved the problem ... while being absurdly opaque.
So first of all we can turn gla into a function which gets passed a continuation to call rather than knowing it must call itself:
(define (gen-list low high)
(let ([gla (λ (cont i result)
(if (< i low)
result
(cont cont (- i 1) (cons i result))))])
(gla gla high '())))
And then, of course we can turn (let ([x y]) ...) into ((λ (x) ...) y):
(define (gen-list low high)
((λ (gla)
(gla gla high '()))
(λ (cont i result)
(if (< i low)
result
(cont cont (- i 1) (cons i result))))))
And that's a nice, pure answer ... which no student would ever come up with.
An alternative approach which is even more malicious is just to explicitly use the Y combinator, of course.
Just adding tail call recursive version
(define (gen-list start end (acc '()) #:step (step 1))
(cond ((> start end) (reverse acc))
(else (gen-list (+ start step) end (cons start acc)))))
Personally I love cond because you have all the conditions then below each other (or an else) - this is the style of The little Schemer a very good book for learning recursive thinking.
You need more than just the (> start end) base case, you also need a (= start end) base case in which you return (list start)

Typed racket error with check-random

I'm trying to convert a project over to typed racket from racket and I'm encountering errors with working code because of the testing engine.
I've reduced it to the smallest piece of code I can create that reproduces the problem:
#lang typed/racket
; provides check-expect and others for testing
(require typed/test-engine/racket-tests)
(: bar (-> Positive-Integer Integer))
(check-random (bar 6) (random 6))
(define (bar x)
(random x))
(test)
And the errors are:
. Type Checker: type mismatch
expected: Pseudo-Random-Generator
given: Any in: (check-random (bar 6) (random 6))
. Type Checker: type mismatch
expected: Positive-Integer
given: Any in: (check-random (bar 6) (random 6))
. Type Checker: Summary: 3 errors encountered in:
(check-random (bar 6) (random 6))
(check-random (bar 6) (random 6))
(check-random (bar 6) (random 6))
Does anyone have any advice on how to fix this? I really want to be able to use the type checking features if possible.
Thanks
Sure, I can help, but it depends a lot on what exactly you want, and where you're going with this.
Short overview: there are multiple testing frameworks for Racket. You're using the one that's built for the teaching languages. It has several nice features, but generally speaking rackunit is the testing framework used by others.
It appears to me that the typed version of the teaching-language-test-framework doesn't include support for check-random. I'll check on this on the mailing list. That would steer you toward rackunit.
Unfortunately, rackunit doesn't include the "check-random" form. Fortunately, it's not hard to implement. Here's my implementation, attached to your code.
#lang typed/racket
; provides check-expect and others for testing
(require typed/rackunit)
;; create a new prng, set the seed to the given number, run the thunk.
(: run-with-seed (All (T) ((-> T) Positive-Integer -> T)))
(define (run-with-seed thunk seed)
(parameterize ([current-pseudo-random-generator
(make-pseudo-random-generator)])
(random-seed seed)
(thunk)))
;; run a check-equal where both sides get the same PRNG seed
(define-syntax check-random-equal?
(syntax-rules ()
[(_ a b) (let ([seed (add1 (random (sub1 (expt 2 31))))])
(check-equal? (run-with-seed (λ () a) seed)
(run-with-seed (λ () b) seed)))]))
(: bar (-> Positive-Integer Integer))
(define (bar x)
(random x))
(check-random-equal? (bar 6)
(random 6))
I should probably tell you about several important differences between the two testing frameworks.
You don't need to call "(test)" at the end; the tests run interleaved with the rest of the code.
Since the tests are interleaved with the code, they must appear below all of the definitions required to run the test.
Nothing is printed when a test succeeds.

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

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))

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.

Add lists to a list lisp

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