[plt-scheme] awkwardness in automarking

From: Dave Herman (dherman at ccs.neu.edu)
Date: Thu Dec 21 20:15:52 EST 2006

Given that the language levels have different semantics, it seems 
problematic to test student programs in the wrong language levels. (I 
don't know if there are "conservative extension" guarantees, but 
regardless your experience has shown that this is problematic.)

I don't know exactly what your TAs' autograding scripts are trying to 
do, but here's a few thoughts:

1) I believe that teachpacks can be written in any language level. 
That's one avenue you might explore.

2) Another approach is to `read' the source code, wrap it with a module 
declaration with the right language level, and use `eval' or 
`dynamic-require', a la:

     (let ([src (read ...)])
       `(module foo (lib "htdp-beginner.ss" "lang") ,src))

But you won't be able to require or provide anything that way, so all 
you can do is observe side effects.

3) Finally, here's an even more elaborate hack. You could create a 
variation on the relevant language level that just reprovides everything 
from the original language level in addition to "provide". In case 
"provide" might clash with a name in the student's program, you can 
rename it to something obfuscated (I'll use __PROVIDE__ in the example). 
Here's how you might wrap the beginner language level:

;; --
(module htdp-beginner-for-grading (planet "mzlite.ss" ("dherman" 
"mzlite.plt" 1 0))
   (require (all-except (lib "htdp-beginner.ss" "lang") #%module-begin 
#%app #%top #%datum)
            (rename (lib "htdp-beginner.ss" "lang") htdp:module-begin 
            (rename (lib "htdp-beginner.ss" "lang") htdp:app #%app)
            (rename (lib "htdp-beginner.ss" "lang") htdp:top #%top)
            (rename (lib "htdp-beginner.ss" "lang") htdp:datum #%datum))
   (provide (all-from (lib "htdp-beginner.ss" "lang"))
            (rename htdp:module-begin #%module-begin)
            (rename htdp:app #%app)
            (rename htdp:top #%top)
            (rename htdp:datum #%datum)
            (rename provide __PROVIDE__)))
;; --

This creates a module that's in a completely empty language level (my 
"mzlite" language level in PLaneT is a way of creating a module that 
doesn't import any of the standard bindings of mzscheme except for 
`require', `provide', and the core module forms (#%app etc.). This way 
you can require the htdp-beginner language level without its names 
conflicting with the mzscheme versions of those names, and then reexport 
them without change. Then you also export the `provide' name (but 
renamed to be obfuscated if you wish).

Once you've got this new, wrapped version of htdp-beginner, it should 
not alter the semantics of the student's program at all, and you can 
wrap the program in code that provides whatever particular functions you 
want to test:

     (let ([src (read ...)])
       `(module student-45 "htdp-beginner-for-grading.ss"
          (__PROVIDE__ exercise1 exercise2 exercise3)))

Just some thoughts. I'm not sure if this addresses your needs exactly, 
but I don't know exactly what your TA's are trying to do with the code.

Good luck,

Prabhakar Ragde wrote:
> My TAs, who run scripted automarking tests on submitted student code, 
> report that students using early HtDP language levels (say, Beginner) 
> occasionally use identifiers, such as "time", that have meaning in 
> higher language levels. The TAs were running their tests in Advanced by 
> using "load" (I think -- I haven't looked at what they're doing in 
> detail) and the student code was failing because of redefining "time", 
> whereas it would have run in Beginner. I suggested going to Pretty Big, 
> but the syntax of define-struct is different, and tests again seem to 
> break. Is there an elegant solution to this? Thanks. --PR
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme

Posted on the users mailing list.