Checking Helper Functions and Recursion

This page assumes knowledge of how to do rst test setups for cs135 (TestingGuide), how options.rkt files work (OptionsRkt), and how instructor-scripts work (OptionsRkt).


Inside /u/cs135/marking/provided-library/analyze-helpers are the scripts which you can use to do a number of checks related to helper functions and recursive functions. To use this you want to copy this analyze-helpers directory inside the provided directory inside the testing directory (, test.0, etc) - so It is used as an instructor script. For each question part you want to do these checks, you want to make a copy of inside the same directory ( . For example, say for question 2c) students are required to define a function named my-function, but they are not allowed to use self defined global helper functions or recursion. They are allowed to use the functions they defined in 2a) and 2b), my-2a-function and my-2b-function which are recursive. So you would make a copy of, called and set the variables inside the file as follows:


  • The required_functions variable is set to the function name(s) that is being checked.
  • If checkprovided is set to true then it will only pass a student's submission if they call the function named in the provided_helper variable. Note that it doesn't work if that function is not called explicitly (for example passed into another function, like in map, filter, etc).
  • If globalhelpers is set to true, then it will ban any usage of global helper functions except the functions mention in allowed_helpers. Note that this ban does not include built-ins.
  • If allhelpers is set to true, then it will ban any usage of local or global helpers except for the global functions mention in allowed_helpers. Note that this ban does not include built-ins.
  • If allrecursion is set to true, then it will ban the required function and any of its helpers from being recursive.
  • If mainrecursion is set to true, then it will only ban the required function from being recursive but its helpers can be recursive.

After you have set the variables to suit your needs, then if it does not already exist, create an options.rkt in and add the following line to it:

(instructor-script "provided/analyze-helpers/")

Note that you can only have one instructor-script per options.rkt file. Additionally, if the outer options.rkt (inside in/) file also has the instructor-script constant defined, then this one will overwrite it. Similarly if an options.rkt inside a specific test, for example in/2b/001/options.rkt has the instructor-script constant defined, then the one in in/2b/001/options.rkt will overwrite the constant in in/2b/options.rkt for only test 001, not the other tests. For each test, the innermost constant definition for a particular constant is used.

Also note, that a local helper named fn would actually be named fn#x where x is some combination of numbers behind the scenes. A global function named fn would still be fn behind the scenes.This is to differentiate functions from functions with the same name in other scopes. Keep this in mind as it may affect your understanding of how these scripts work.


We can expand on the functionality of this script. All the needed scripts are in the analyze-helpers directory that you copy over. If you do add new functionality make sure to update the master scripts inside marking/provided-library/analyze-helpers after testing your changes. The scripts call analyze-helpers.rkt which has functions defined to do the specific checks that are asked for. In order to scan the student file and get all this information about helpers and recursive functions, the analyze-helpers.rkt script uses library functions defined in static-analysis.rkt - a library written by Dan Holtby. This library has a lot of useful functions which can be called to get all sorts of information from a student's file.

If static-analysis.rkt already has the library functions that you need for whatever you want to do, then you only need to add a way to use those functions properly inside analyze-helpers.rkt and add some commands to call it inside You can look inside both of these scripts to see how the previously implemented things are done. Some of these may not have had the best coding practices used because they were written hours before they needed using, so feel free to refactor as well, as long as you test it properly. Always make backups before you make changes.

If statis-analysis.rkt does not have the library functions you need, then that is more complicated. You need to know some good full racket to add to it, if Dan is available, then you can also reach out to him for help. A quick reference of what static-analysis.rkt has at the time of writing this is below:

(static-analysis filename) will produce a global name map (hash table). This is used as the first parameter to a bunch of functions old and new.

All "name"s below are symbols representing function names. gnm is the global name map mentioned in the line above.

(extract-helpers gnm name) produces a list of all global helpers called by name (including itself)

(extract-all-helpers gnm name) produces a list of all helpers (local and global) called by name, or called by helpers called by name, or called…you get the idea. You can also add a third optional parameter, a list of symbols representing function names of built-ins that if called by name or its helpers, also appear in the helper list produced. If not called, then they won't appear. This is useful for checking if a student is using a function we provided in a different file, since a function included from another file behaves as a built-in.

(extract-local-helpers gnm name) as extract-all-helpers but restricted to local helper functions…this does include local helpers called by global helpers

(extract-global-helpers gnm name) as extract-all-helpers but restricted to global helper functions (again, this is a filter applied after the fact, so it will include global helpers called by local helpers).

(recursive? gnm name) produces #t if the function calls itself (including taking part in mutual recursion), #f if it does not, and ‘not-defined if gnm doesn’t contain name.

(uses-recursion? Gnm name) produces #t if either name itself, or any helpers it uses, are recursive? Again, ‘not-defined indicates name doesn’t exist.

(uses-global-helpers? Gnm name) produces #t if name calls at least one globally defined function (other than itself), #f if it doesn’t, ‘not-defined if it isn’t defined

(uses-local-helpers? Gnm name) produces #t if name calls at least one locally defined helper…this includes if it calls global helpers and those have their own locals. Maybe not useful info.

(helper-usage-statistics gnm func-names) produces a hash table where the keys are global helper function, and the values are how many of the functions in func-names have references to them. If func-names is left off, or is #f, then the counts are how many different global functions call each helper in total.

Topic attachments
I Attachment History Action Size Date Who Comment
PNGpng analyze-helpers-clip.png r1 manage 47.8 K 2022-04-28 - 15:43 BaniSingh Screenshot of portion of to demonstrate an example
Edit | Attach | Watch | Print version | History: r3 < r2 < r1 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r3 - 2022-04-28 - BaniSingh
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback