Common MathObject Methods

From WeBWorK_wiki
Revision as of 16:58, 10 August 2012 by Dpvc (talk | contribs)
Jump to navigation Jump to search

There are a number of methods that are common to all MathObjects, which are described below. Some classes have additional methods, and many of these are listed in the documentation for the individual MathObject Classes. You call a method on a MathObject as you would a method for any Perl object, using the -> operator with the MathObject on the left and the method name and its arguments (if any) on the right. E.g.,

   $mo->method;              # when there are no arguments
   $mo->method($arg);        # for one argument
   $mo->method($arg1,$arg2); # for two arguments
   # and so on


Methods Common to All Classes

Method Description
$mo->cmp
$mo->cmp(options)
Returns an answer checker for the MathObject. The cmp method can accept a number of settings that control the tolerances for the comparison, special options of the comparison (e.g., parallel vectors rather than equal vectors), the types of error messages produced (e.g., messages about individual coordinates that are wrong), and other features of the check. These are described in the MathObjects Answer Checkers POD documentation. All of the answer checkers are defined in the file pg/lib/Value/AnswerChecker.pm.
$mo->value Returns an array containing the data that represents the object. For a Real, it is just the perl real number that corresponds to it; for a Complex number, it is the real and imaginary parts (as Reals). For an Infinity, it is the string needed to obtain the Infinity. For a Point or Vector, it is the coordinates of the Point or Vector (as MathObjects). For a Matrix, it is an array of rows of the Matrix, where the rows are references to arrays of MathObjects. For an Interval, it is the two endpoints (as Reals) followed by strings that are the open and close parentheses or brackets for the Interval. For a Set, it is an array of the elements of the set (as Reals). For a Union, it is an array of the Sets and Intervals that make up the Union. For a String, it is a perl string representing the value of the string.

For a Formula, it is a little more complicated. If the Formula is an explicit Point, Vector, Matrix, Interval, etc. (e.g., Formula("<x,x+1>")), then the value is an array of Formulas that are the coordinates. If the Formula is an expression (e.g., Formula("<x,1> + <2x,-x>") or Formula("norm(<x,x+1>)") then the value is just the original Formula.

$mo->data Returns a reference to the array of data that represents the object.
$mo->length Returns the number of elements in the array returned by the value() method, e.g., the number of coordinates in a point or vector, or the number of rows in a matrix.
$mo->extract(i,...) Returns the [math]i[/math]-th element from the data for $mo. If more than one index is used, recursively extracts from the result, so that for a Matrix, $M->extract(i,j) returns the [math](i,j)[/math]-th entry, and for a list of lists, $L->extract(i,j) is the [math]j[/math]-th element of the [math]i[/math]-th list.
class->new(data)
$mo->new(data)
Creates a new instance of the class or the class of $mo using the given data. This what the various class constructor functions do; e.g., Real(5) effectively calls Value::Real->new(5).
class->make(data)
$mo->make(data)
Creates a new instance of the class or the class of $mo using the given data, but without all the error checking of type conversion. So data must be an array of MathObjects of the correct type. This is used internally when the types of the data are known to be correct, for efficiency, but it is always safer to use new.
$mo->with(name => value) This copies the object, and sets its property with the given name to the given value. You can supply multiple name/value pairs separated by commas. This gives you the ability to initialize the object when you create it, or to make a copy with specific settings. E.g.
   $f = Formula("sqrt(x-10)")->with(limits => [10,12]);
   $a = Real(pi/2)->with(period => 2*pi);

Note that the copy is not a deep copy (i.e., if $mo has references to other objects, the returned object will reference the same ones rather than copies of them). In particular, this is the case for the {data} property. Use $mo->copy to get a deeper copy, or $mo->new($mo->string) to get a separate version that shares no data with $mo

$mo->without("name",...) Returns a copy of $mo where the named properties have been removed. Note that, as with with(), the copy is not a deep one, so the two copies of $mo will share any references to other objects. In particular, this is the case for the {data} property. Use $mo->copy to get a deeper copy, or $mo->new($mo->string) to get a separate version that shares no data with $mo
$mo->copy Returns a copy of $mo with its {data} array copied as well, so that the copy doesn't share the data with the original. Note that setting $mo2 = $mo1 does not copy $mo1; instead, both $mo2 and $mo1 both point to the same MathObject, so changes to one will change the other. Use $mo2 = $mo1->copy to obtain a separate copy for $mo2.
$mo->context
$mo->context($context)
The first form returns the context in which $mo was created. When passed a reference to a Context object, this sets the context for $mo to be the given context.
$mo->inContext($context) This calls context($context) and then returns $mo so that it can be used in a chain of method calls, e.g.
$f->inContext($g->context)->with(limits => $g->{limits});
$mo->getFlag("name")
$mo->getFlag("name",default)
Returns the object's value for a given context flag. The value can come from a variety of locations, which are searched in the following order (the first that has a property with the given flag name will have that propery's value returned): the object itself, the Formula that created it (if it was the result of an eval() call, for example), the AnswerHash associated with the object (if it was the source for an answer checker; this gives access to the flags passed to the cmp method), the Context in which the object was created, the currently active Context, or the default value (if given as the second argument), otherwise the return value is undef. This is useful in custom answer checkers for finding out the settings of things like the tolerances, the flags passed to the answer checker, and so on.
$mo->typeMatch($object) This determines if the $object is "compatible" with the given MathObject for equality or inequality comparisons. For example, a Real will allow equality comparison to an Infinity, and a Complex will allow comparison to a Real. It is best to use typeMatch in your own custom answer checkers if you need to check if a student's answer is of the correct type rather than using something like ref() to check if the two are the same type of object (which is too restrictive, in general).
$mo->class
$mo->type
These are two methods that help you determine what kind of MathObject you are working with. They can be useful in custom answer checkers if you want to know more about what kind of object a student answer is. The class method tells you the class of object (like Real, Complex, Point, Formula, etc.), while the type method tells you what kind of return value a Formula has (non-Formulas are considered constant-valued Formulas when computing the type). The class is essentially the package name from the Value package of the MathObject, while the type is the package name from the Parser package name for the result of the Formula.
   Real(5)->class;          # produces "Real"
   Real(5)->type;           # produces "Number"
   Point(1,2)->class;       # produces "Point"
   Point(1,2)->type;        # produces "Point"
   
   Formula("3x+1")->class;  # produces "Formula"
   Formula("3x+1")->type;   # produces "Number"
$mo->TeX Returns a string which represents the object in [math]\rm\TeX[/math] format. For example
   $f = Formula("(x+1)/(x-1)");
   BEGIN_TEXT
   The formula is \(f(x) = \{$f->TeX\}\).
   END_TEXT

Since it is common to need the [math]\rm\TeX[/math] expression in the problem's text, there is a special Context setting that tells MathObjects to output their [math]\rm\TeX[/math] format whenever they are substituted into a string. That is enabled via the Context()->texStrings command, and turned off by Context()->normalStrings, as in the following example:

   $f = Formula("(x+1)/(x-1)");
   Context()->texStrings;
   BEGIN_TEXT
   The formula is \(f(x) = $f\)
   END_TEXT
   Context()->normalStrings;

This avoids having to call the TeX() method, and prevents the need for using \{...\} to get the [math]\rm\TeX[/math] format.

$mo->string Returns a string similar to that used to create the object, in the form that a student would use to enter the object in an answer blank, or that could be used in Compute() to create the object. The string may have more parentheses than the original string used to create the object, and may include explicit multiplication rather than implicit multiplication, and other normalization of the original format.
$mo->perl Returns a string which represents the object as Perl source code. This is used internally, and would rarely be needed in a PG problem.
$mo->eval
$mo->reduce
All MathObjects have these methods, but for most, they just return $mo. They are mostly used for the Formula class, but are available on all so that you don't have to check the type before calling them. A few classes, like Unions, implement reduce().
$mo->ans_rule(width)
$mo->named_ans_rule(width)
$mo->named_ans_rule_extension(width)
These operate like the PG macros of the same names, but are here as the counterpart to the ans_array methods below. That way, you can call one or the other in order to get the proper answer rules for $mo. It also helps to see what answer rule goes with what answer if you use \{$mo->ans_rule(10)\} in your BEGIN_TEXT/END_TEXT blocks rather than just \{ans_rule(10)\}.
$mo->ans_array(width)
$mo->named_ans_array(width)
$mo->named_ans_array_extension(width)
For Points, Vectors, and Matrices, these produce multiple answer blanks, one for each coordinate or entry, that are all tied to the one answer checker for $mo. This forces (or allows, depending on how you look at it) the student to enter each coordinate separately, while you still only need to handle one answer checker. See the Matrix documentation for an example.
$mo->isZero Returns 1 if $mo corresponds to whatever zero means for that type (e.g., for a Vector, it is a zero vector), and 0 otherwise.
$mo->isOne Returns 1 if $mo corresponds to whatever one means for that type (e.g., for a Matrix, it is an identity matrix), and 0 otherwise.
$mo->isSetOfReals Returns 1 if $mo is an Interval, Set, or Union (or subclasses of those), and 0 otherwise.
$mo->canBeInUnion Returns 1 if $mo is an Interval, Set, or Union, or is another object whose string version could look like an Interval (e.g., a Point with two coordinates where the first is less than the right). This is used in contexts where parentheses can produce Points, for example, to promote them to Intervals when appropriate.
$mo->showClass Returns a string representing the class of $mo suitable for use in error messages. The string includes "an" or "a", so
Value->Error("You can't take the square root of %s",$mo->showClass)

could produce the message "You can't take the square root of a Vector".

$mo->showType Returns a string representing the type of $mo suitable for use in error messages. Note that the class and the type are not the same; e.g., the type of a Formula is the type of it return value, while it's class is Formula (actually Value::Formula). So $f->showClass might be "a Formula returning a Real Number" for a formula $f, while $f->showType would produce "a Real Number".
$mo->inherit($mo1,...) Copy the properties that are not already present in $mo from $mo1 (and any other objects passed to it). This is used by things like the binary operations to make sure that the result inherits the attributes of the the two operands.
$mo->noinherit Returns the list of properties that should not be copied by inherit().
$mo->Package($context,"class",$noerrors) Returns the name of the package that implements the given class in the given Context. For example, $mo->Package($mo->context,"Real") probably will return "Value::Real". The Context could have override the default package for Reals, however, to use a subclass of Reals that implements additional functionality, in which case that subclass package name would be returned.


Support Functions

These are functions that are part of the Value package, but do not refer to a MathObject directly, so are not methods of any class. You call them from the Value package directly. Mostly they are general utility functions, or functions that test an unknown value to see if it is a MathObject or could be converted to one.

Method Description
Value->Error(message,$s1,...) Produces an error message by inserting the values of $s1 and any other arguments into the message using printf-style substitution, and then throws an error condition (i.e., your program or subroutine will stop at that point). If used in a custom answer checker, the error usually will appear in the messages area of the results table at the top of the page. For example,
Value->Error('You can't take the square root of %s',$mo->showType)
might produce the message "You can't take the square root of a Vector".
Value->NameForNumber(n) Returns a string like "first", "second", etc. that can be used in an error message. For example,
Value->Error("Your %s point is incorrect",Value->NameForNumber(i))

would produce the message "Your fifth point is incorrect" when i is 5. This can be useful in custom answer checkers that deal with lists of objects or coordinates of points or vectors.

Value::contextSet($context,flags) This sets the given flags to the given values in the given context and returns a hash representing the flags and their original settings. This is useful if you want to change the settings of flags temporarily (e.g., in an answer checker), but want to reset them when done. For example,
   my $flags = Value::contextSet($correct->context,
      reduceConstants => 1,
      reduceConstantFunctions => 0,
   );
   ... do something with Formulas here ...
   Value::contextSet($correct->context, %{$flags});

would set the value of reduceConstants and unset reduceConstantFunctions and return the original settings in $flags. After the processing that needs these flag settings is complete, the second call to contestSet() returns the values to their original settings.

Value::protectHTML(string) Returns a string where HTML special characters have been properly escaped (e.g., <, > and & have been replaced by their corresponding HTML entities.
Value::preformat(string) Returns a string where HTML special characters have been replaced by their HTML entities, and newlines have been replaced by <br>.
Value::makeValue(data) Attempts to convert the data into an appropriate MathObject and returns that. For example, a Perl real will be converted to a Real object, and a string will be converted to a String, provided it is in the current Context. It is safe to pass a MathObject to makeValue(), as it will be returned without change; thus you can use $x = makeValue($x) to guarantee that $x is a MathObject.
Value::matchNumber(string) Returns 1 if the contents of the string would be interpreted as a (signed) number in the current Context, undef otherwise.
Value::matchInfinite(string) Returns 1 if the contents of the string would be interpreted as an infinity in the current Context, undef otherwise.
Value::classMatch($mo,"class",...) Returns 1 if $mo is a MathObject belonging to one of the classes specified, and 0 otherwise. To be considered in the given class, $mo must satisfy one of the following:
  1. Its class() method returns the name of the given class. (Note that class() usually returns the last component of the object's package name, so an object in package my::Real would have class() return "Real" so could match Value::matchClass($mo,"Real").
  2. Its package name is "Value::class" for the given class.
  3. The value of $mo->{isClass} is defined an non-zero (e.g., if $mo->{isReal} = 1, then Value::matchClass($mo,"Real") is true).
  4. The package for $mo is the same as the Context's package associated with the given class (e.g., Value::matchClass($mo,"Real") will be true if $mo->context->{value}{Real} is ref($mo)).
  5. Its class is a subclass of Value::Class for the given class, and $mo->{isClass} is not 0.

These conditions are checked for each class name passed to classMatch() until one matches or the end of the list is reached. It is safe to pass a non-MathObject to classMatch() as no methods are called directly on $mo.

Value::isContext($x) Returns 1 if $x is a reference to a Context object, undef otherwise.
Value::isParser($x) Returns 1 if $x is an instance of a class that is a subclass of Parser::Item (i.e., is part of a parse tree for a Formula object), and undef otherwise.
Value::isValue($x) Returns 1 if $x is a MathObject, and undef otherwise. To be a MathObject, $x must satisfy one of the following
  1. It is in a package whose name begins with Value::
  2. It has the {isValue} set to something other than 0 (e.g., $mo->{isValue} = 1, or
  3. It is an instance of a subclass of the Value class.

The latter two are the usual ways to make your own classes that act as MathObjects.

Value::isFormula($x) Shorthand for Value::classMatch($x,"Formula")
Value::isReal($x) Shorthand for Value::classMatch($x,"Real")
Value::isComplex($x) Shorthand for Value::classMatch($x,"Complex")
Value::isNumber($x) Returns 1 if $x represents a number, undef otherwise. If $x is a Formula, this is true when its return value is a number; otherwise it is true when Value::classMatch($x,"Real","Complex") or Value::matchNumber($x) is true. Note that this is true when $x is a Complex number as well as a Real number.
Value::isRealNumber($x) Returns 1 if $x represents a real number, undef otherwise. If $x is a Formula, this is true when its return value is a Real number; otherwise it is true when Value::classMatch($x,"Real") or Value::matchNumber($x) is true.