Test Constants and Helper Functions (old)
When a student has to define a structure in their submitted file it is hard to write test constants and helper functions for that structure. One way to do this is to make your own version of the structure and convert everything into vectors. Suppose the students are asked to write some function that outputs a list of cells. The students must also define the cell struct in their submitted file. This means that you cannot use the cell structure in any provided files.
To get around this follow the example provided in the appendix. Any functions or constants that are provided have a random string after them. This is done to avoid naming conflicts with students code. In full racket structs must be transparent if you want to access the fields. Next, define functions that access a structs fields by converting it to a vector. This is the most important part because it allows for fields of an undefined struct to be accessed. For convenience, they are wrapped by a function with the same name that struct cell would have. With this you can now define any test constants and helper functions needed. The constant input1-cs135 could be a possible input to the students function, with output1-cs135 as the expected output. The test.rkt file may look something like the following.
(result (list-equiv?_645 (student-fn input1-cs135)
(output1-cs135)))
(expected true)
Remember that any helper files you write will be in full racket. Also make sure not to use functions that are disallowed.
<a name="Example file"></a>Example file
for test constants and helper functions. For the functions being provided, it is important to end them with -cs135, incase students also have functions with the same name to prevent name errors when testing.
#lang racket
(provide list-equiv?-cs135 input1-cs135 output1-cs135 check-within-cs135)
(define-struct my-cell (x y used?) #:transparent)
;; A Cell is a (make-my-cell Nat Nat Bool)
;; Defining these functions allows you to directly transfer any code
;; in your solutions into this file
(define make-cell make-my-cell)
(define (cell-x c) (vector-ref (struct->vector c) 1))
(define (cell-y c) (vector-ref (struct->vector c) 2))
(define (cell-used? c) (vector-ref (struct->vector c) 3))
(define c1 (make-cell 0 0 false))
(define c2 (make-cell 1 0 false))
(define c3 (make-cell 2 0 false))
(define c4 (make-cell 1 0 true))
(define c5 (make-cell 2 0 true))
(define input1-cs135 (list c1 c2 c3))
(define output1-cs135 (list c1 c4 c5))
;; (check-within-cs135 val target range) Determines if the val is close enough to
;; target, with a threshhold of range
;; check-within-cs135: Num Num Num -> Bool
(define (check-within-cs135 val target range)
(< (abs (- val target)) range))
;; In practice this function will be comparing a cell defined in this file
;; with a cell define in a studens file.
(define (cell-equiv? cell1 cell2)
(and (equal? (cell-x cell1) (cell-x cell2))
(equal? (cell-y cell1) (cell-y cell2))
(equal? (cell-used? cell1) (cell-used? cell2))))
;; (list-equiv?-cs135 lst1 lst2) determines if two lists contain all of the
;; same elements regardless of order.
;; list-equiv?-cs135: (listof Cell) (listof Cell) -> Bool
;; This function will only work if abstract list functions are allowed
(define (list-equiv?-cs135 lst1 lst2)
(local
[;; like member?, but comparing using cell-equiv? instead of equal?
(define (cell-mem? cell lst)
(ormap (lambda (c) (cell-equiv? cell c)) lst))]
(and (= (length lst1) (length lst2))
(andmap (lambda (c) (cell-mem? c lst2)) lst1)
(andmap (lambda (c) (cell-mem? c lst1)) lst2))))
- examplelib.rkt: This is a file containing the example at the bottom of the page
<a name="Alternative solutions"></a>Alternative solutions
I could not get the above method to work in my term; it seems like you would have to do define-syntax, not just define, on all the functions associated with cell. Otherwise, the student’s file will crash when it tries to call things like cell-x on something that is a my-cell and not a cell.
If the assignment has reached Intermediate Student level when functions can be used as values, you can define your own version of the struct, plus a function which converts your struct into the student’s struct, using the constructor and your struct as arguments. For example:
(define (cast-cell ctor other-cell)
(ctor (my-cell-x other-cell)
(my-cell-y other-cell)
(my-cell-used? other-cell)))
(cast-cell make-cell test-cell-1)
If you are working with recursive definitions like trees, use abstract list functions to help write your cast function! Hopefully, if you are still in Beginning Student, the structures are simple enough that it’s quick to just write them directly in test.rkt.
Comments