Is there a(n easy) way to add a function to the current Context? For example, suppose I wanted to have my own step function, defined to be mystep(t) = zero for t less than 28 and 3 for t greater than or equal to 28, and wanted students to be able to use this in their answer. The first guess would be that there might be some mechanism like Context()->functions->add( mystep => $sub ), where the variable sub is a reference to a subroutine that does the actual function calculation.
However, I didn't see anything like that when I looked at the code, and I suspect that there's probably a good reason why that wouldn't actually be as clean as I'm imagining.
It did look as if it might be possible to add some library file that parallels the existing numeric, trig, etc., functions, and then add the new category to the %Categories hash in the Context, but again I'm probably not thinking of all of the complications that might elicit.
There is a macro file parserFunction.pl that lets you add a new function to the context in such a way that the student can use it, but the way the function is defined is to use a Formula() object, which will not be sufficient for your needs unless you want to use contextPiecewiseFunctions.pl as well. In that case you could do something like the following (untested) code:
loadMacros( "contextPiecewiseFunction.pl", "parserFunction.pl", ); Context("PiecewiseFunction")->variables->are(t => 'Real'); parserFunction(myStep => PiecewiseFunction("0 if t < 28 else 3"));Of course, this means students will be able to enter piecewise functions using if and else as well.
Alternatively, you can role your own additional function by making a subclass of the appropriate Parser class (in this case Parser::Function::numeric) that implements the desired step function. An example is given in webwork2/doc/parser/extensions/1-function.pg that you should be able to modify to your needs.
Note that in either case, you will need to be careful about setting your limits for the function and about forcing test points that guarantee that both parts of the step are tested. For example, the myStep that is defined above would match the function 0 using the standard limits.
loadMacros( "contextPiecewiseFunction.pl", "parserFunction.pl", ); Context("PiecewiseFunction")->variables->are(t => 'Real'); $myStep = PiecewiseFunction("0 if t < 28 else 3") Context("Numeric")->variables->are(t => 'Real'); parserFunction(myStep => $myStep);That lets the problem use the piecewise function to define myStep() but not let students enter piecewise functions.
That's great; thanks! I should have used a different example than the step function, because it was really just there because it was the easiest example I could think of, not because that's the desired function.
The function documentation you pointed out and subclassing method should work great, however.