Reputation: 1365
I have a programming project for which I am attempting to write some test cases for.
To simply things, I wrote a method to run these test cases:
(define print-case
(lambda (st1 st2 func)
(begin
(if (equal? func intersection)
(display "Intersection ")
(display "Union "))
(display " of ")
;???
(print (func st1 st2))
(newline)
)
)
)
I have several lists defined to run and two methods.
Here are some of the lists:
(define set1 '(1 4 9 7 20))
(define set2 '(15 4 7 25 99))
However, to save trouble, I want the names of the sets and the functions to be printed, not the expansions of them. Is this possible?
I tried (display st1)
, but obviously that just expands st1 into the list. Putting a single quote in front of st1 just causes it to print st1, not the name of the set I passed in.
Thanks in advance.
Upvotes: 0
Views: 54
Reputation: 48745
You are aware you can use rackunit
for unit tests:
(require rackunit)
(check-eq? (car '(b b)) 'a "car-test")
==>
--------------------
FAILURE
actual: b
expected: a
name: check-eq?
location: (unsaved-editor1044 5 0 35 38)
expression: (check-eq? (car '(b b)) 'a)
message: "car-test"
Anyways, if you want to roll your own you need to use a macro:
(define-syntax unit-test
(syntax-rules ()
((_ (form . args) expected-result)
;; insteadof this let one could make a procedure to handle it and pass expression quoted and unquoted.
(let ((res (form . args))
(exp expected-result))
(when (not (equal? res expected-result))
(display "Error: ")
(display '(form . args))
(newline)
(display "Got result '")
(display res)
(display "' expected '")
(display exp)
(display "'")
(newline))))))
(unit-test (+ 4 5) 10)
==>
Error: (+ 4 5)
Got result '9' expected '10'
Upvotes: 2
Reputation: 85823
In Common Lisp, you could define your variables set1
and set2
as global variables with defparameter
, defvar
, or defconstant
, and use symbol valueto get the value of the variable using the symbol that names it. E.g.,
(defparameter set1 '(1 4 9 7 20))
(defparameter set2 '(15 4 7 25 99))
(defun print-case (name)
(format t "~a ~a" name (symbol-value name))
In Scheme, you won't be able to do that though. If you want to be able to take symbols and get corresponding values, in general, you'll need to build some kind of structure that associates the symbols with the values. You could use an association list:
(define sets '((set1 1 2 3 4 5)
(set2 0 1 3 5 7)))
(cdr (assoc 'set1 sets))
;=> (1 2 3 4 5)
(cdr (assoc 'set2 sets))
;=> (0 1 3 5 7)
Alternatively, you could use a hash table:
(define sets
(hash 'set1 '(1 2 3 4 5)
'set2 '(0 1 3 5 7)))
(hash-ref sets 'set1)
;=> '(1 2 3 4 5)
(hash-ref sets 'set2)
;=> '(0 1 3 5 7)
In any case, you'll need to provide some sort of structure that maps from symbols to lists.
If you don't need such a general solution, though, you could use some macros, as uselpa's answer demonstrates, and could wrap the test function in such a way that you have access to both the symbol that the test function is called with and the value of the variable with that name. That doesn't “map” from symbols to values in the same way, but your test function would get the four values that it needs (two names and two values), and for writing test cases, that's probably enough.
Upvotes: 1
Reputation: 18917
In your example, the names set1
and set2
are not know inside print-case
, so it's not possible. Either you pass the names explicitly, or you could use a macro to wrap it:
(define-syntax-rule (call-print-case s1 s2)
(apply print-case `(s1 ,s1 s2 ,s2)))
(define set1 '(1 4 9 7 20))
(define set2 '(15 4 7 25 99))
(define print-case
(lambda (st1name st1 st2name st2)
(display st1name)
(displayln st1)
(display st2name)
(displayln st2)))
then
(call-print-case set1 set2)
=>
set1(1 4 9 7 20)
set2(15 4 7 25 99)
Upvotes: 3