### 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()`