Re: Undefined subroutine error when adding function to context
by Paul Pearson -Re: Undefined subroutine error when adding function to context
by Davide Cervone -Note that math expressions in a PG problem can be computed in two very different ways: using native Perl code, or using MathObjects. The MathObject library tries to make these two as similar as it can, but you do need to be aware of the differences. I'm going to write a longish explanation below, and you will already know a lot of it, but there are some points that are important to my answer at the end.
When you write
$y = log($x)/log(2);for example, you are using Perl mathematical computation. (Perl variables start with a dollar sign, you have not used
Compute()
or Formula()
, or quotation marks, etc.). Note that in Perl expressions, exponentiation is done via **
not ^
, and multiplication is explicit, so you must write
$y = 3*$x**2;not
y = 3x^2
when you are doing perl mathematics.
MathObjects math is generally done through Compute()
or Formula()
or one of the other constructor functions (Real()
, Complex()
, Interval()
, etc.). These take a string representation of the expression and convert it into an object that represents the result. So you would write
$f = Compute("log(x)/log(2)");to get a Formula object representing the given expression, and you can do
$y = Compute("3x^2");to get a formula for this quadratic.
The connection between the Perl and MathObject formulas, and a source of part of the confusion, is that once you have a MathObject, if you use it in a Perl formula, the result will be a MathObject for the Perl formula. For example
$x = Compute("x"); $f = log($x)/log(2);is effectively the same as
$f = Compute("log(x)/log(2)");(The first line creates a
Formula()
for the identity function and calls that $x
in Perl, and when that is used in log($x)
the result is a Formula for the log of x. When that is divided by the log of 2, the result is a Formula comparable to the one given above). This is one of the powerful features of MathObjects, but it is also one of the places where confusion can occur.
The meaning of expressions computed by MathObjects are controlled by the MathObject Context()
. This defines what operators, functions, variables, and so on, are allowed in the formulas that are produced by Compute()
and the various constructor functions.
When you do
Context()->functions->add( log2 => {class => 'my::Function::numeric', TeX => '\log_2', nocomplex => 1}, );you are adding a function named
log2
to the context, so that it can be used in formulas produced by Compute()
(and since student answers are processed by Compute()
, you are adding log2
to the things they can type in their answers).
Note, however, that you are not modifying perl expressions by doing this, only MathObjects. Native perl code does't know about MathObjects contexts, and so you have not added log2()
to the things you can type in a Perl expression. If you do
$y = log2($x);at this point, you will get the message about
main::log2
not being defined that you list above. That is because log2
is only defined within the MathObject context, not in native Perl expressions, and the expression above is a native Perl one, not a MathObject one.
To make log2()
available in native Perl, you must also define a native Perl function. Note that near the bottom of the section on adding functions that you link to in your message, it says that you need to use
sub log2 {Parser::Function->call("log2",@_)}in order to be able to use
log2()