2.6: Legacy PG and deprecated patterns

The ADAPT WeBWorK Handbook · LibreTexts

0%

Contents

    Text

    Size
    100%
    Theme
    Typeface
    Line length
    Spacing

    From LibreTexts, under CC BY 4.0, as the source states it; its equations are written in TeX, which the PDF shows typeset. This page at LibreTexts.

    2.6: Legacy PG and deprecated patterns

    This page helps you recognize legacy PG patterns that show up in older problem libraries and online examples. The goal is to translate the useful idea into a PGML-first structure (see Introduction to PGML for modern PGML) without carrying forward fragile formatting or scattered grading logic.

    If you pasted code from an old problem and it uses BEGIN_TEXT, &ANS, or raw Perl formatting, start here.

    If you see a PopUp example online, treat it as a historical artifact, not a recommendation.

    Use this page when: a copied problem looks strange or grades unpredictably.

    Copy and edit (PGML-first rewrite)

    # Legacy text block (do not use)
    # BEGIN_TEXT
    # The stock concentration is $c_stock uM.$PAR
    # Find the final concentration: \{ans_rule(10)\} uM
    # END_TEXT
    
    # PGML-first rewrite
    BEGIN_PGML
    The stock concentration is [c_stock] μM.
    
    Find the final concentration: [________]{$c_final} μM
    END_PGML
    

    Common failure and fix

    Broken: $PAR and BEGIN_TEXT blocks mixed with PGML
    What you will see: raw $PAR output or missing blanks
    Fix: move all prompt text into BEGIN_PGML/END_PGML
    

    Rewrite recipe (fast path)

    1. Identify the story text and move it into a PGML block.
    2. Move all numbers, ranges, and answer objects into Setup.
    3. Attach each answer object directly to the blank in PGML.
    4. Remove unused macros and leftover text-formatting codes.
    5. Render a few seeds to confirm the prompt, units, and grading.

    Legacy patterns to recognize (and replace)

    Legacy patterns to recognize (and replace) reference.
    Legacy pattern Why you see it PGML-first replacement
    beginproblem() call in DOCUMENT section Found in 78% of OPL files. Was once required for initialization but is now handled by DOCUMENT(). Delete the line. DOCUMENT() alone is sufficient.
    BEGIN_TEXT / END_TEXT blocks Pre-PGML format for the prompt text. Use BEGIN_PGML / END_PGML for readable prompt text.
    $PAR, $BR, and manual line breaks Older formatting controls inside text blocks. Use normal paragraphs, lists, or tables in PGML.
    String-built HTML ("

    " . $x . "

    ")
    Manual HTML assembly in PG strings. Use PGML with variable inserts for clean text.
    ANS(num_cmp(...)) or ANS(str_cmp(...)) num_cmp appears in 46% and str_cmp in 7% of OPL files. Legacy evaluators from the pre-MathObjects era. Use MathObjects and PGML inline blanks: [_]{$answer}. See the table below for specific replacements.
    ans_rule() without nearby answer object Older blank creation with separate answer logic. Attach answer objects directly to PGML blanks.
    Manual rounding inside strings Legacy formatting for display-only answers. Use MathObjects and explicit tolerance rules.

    Deprecated or fragile behaviors

    Deprecated or fragile behaviors reference.
    Pattern Why it is fragile Preferred approach
    NchooseK($N, $K) Deprecated in PGchoicemacros.pl. Very common in OPL (1,000+ files). Returns K indices chosen from 0..N-1. Use random_subset($K, 0..$N-1) from PGstandard.pl, or build an index array and @list[@indices].
    shuffle($N) Deprecated in PGchoicemacros.pl. Returns a random permutation of indices 0..N-1. Use random_subset($N, 0..$N-1) for a full permutation, or Perl's built-in list operations.
    new_match_list with print_q/print_a PGchoicemacros.pl legacy match list generates its own form fields, requiring ANS(str_cmp(...)). Use PopUp widgets (parserPopUp.pl) with PGML inline blanks. See Macro Demonstrations for both patterns.
    PopUp menus for choices Legacy UI pattern and inconsistent rendering. Use DropDown or radio/checkbox patterns.
    Hidden grading logic in text assembly Hard to debug and easy to mismatch with the prompt. Compute answers in Setup and attach to blanks.
    Multiple unrelated Context() changes Inconsistent parsing rules across blanks. Set Context once and override only if necessary.
    num_cmp(), str_cmp(), fun_cmp() Legacy evaluators from pre-MathObjects era. num_cmp alone appears in 46% of OPL files. Use MathObjects (Compute(), String(), Formula()) with ->cmp() or PGML blanks. See table below.
    TEXT(beginproblem()) No longer needed. Appears in 78% of OPL files but DOCUMENT() handles initialization. Delete the line entirely. Use DOCUMENT(); alone.
    AnswerFormatHelp.pl Entire macro file deprecated in PG 2.17. Use helpLink() from PGbasicmacros.pl (loaded via PGstandard.pl).
    compoundProblem.pl / compoundProblem5.pl Deprecated in PG 2.19. Legacy multi-section problem macros. Use scaffold.pl with Scaffold::Begin() and Section::Begin().
    Old macro families loaded "just in case" Adds noise and can mask missing dependencies. Load only the macros needed for the prompt.

    Legacy answer evaluators (very common in copied code)

    Before MathObjects existed, every problem used standalone evaluator functions like num_cmp() and str_cmp(). These still work but are discouraged because MathObjects provide richer error messages, tolerance handling, and direct attachment to PGML blanks. If you copy a problem from the OPL, there is roughly a 50% chance it uses at least one of these legacy evaluators.

    Copy and edit (answer evaluator rewrite)

    # Legacy pattern (do not use in new problems)
    # $answer = 42;
    # ANS(num_cmp($answer));
    # ANS(num_cmp($answer, tol => 0.01));
    
    # MathObjects + PGML rewrite
    $answer = Compute("42");
    BEGIN_PGML
    Enter the answer: [_________]{$answer}
    END_PGML
    # Tolerance is set via: $answer->cmp(tolerance => 0.01)
    
    Copy and edit (answer evaluator rewrite) reference.
    Legacy evaluator OPL prevalence What it does MathObjects replacement
    num_cmp($x) 46% (33,804 files) Compares student answer to a number. Supports tolerance, strings like "DNE". $x = Compute("42"); then PGML [_]{$x} or ANS($x->cmp())
    str_cmp("text") 7% (4,958 files) Compares student answer to a string. Used for word answers, matching. $x = String("text"); then PGML [_]{$x} or ANS($x->cmp())
    fun_cmp("x^2") Common in math OPL Compares student formula by sampling points. $f = Formula("x^2"); then PGML [_]{$f} or ANS($f->cmp())
    std_num_str_cmp() Low Hybrid number/string comparator. Formally deprecated in PG 2.17. Use Compute() with appropriate Context.
    numerical_compare_with_units() Low Number comparison with unit checking. Formally deprecated in PG 2.17. Use NumberWithUnits() from parserNumberWithUnits.pl.

    Key point: num_cmp() and str_cmp() are not formally marked deprecated in the PG source (they have been rewritten to use MathObjects internally), but the PG documentation recommends using MathObjects ->cmp() methods directly. New problems should always use MathObjects.

    beginproblem(): safe to delete

    beginproblem() appears in 78% of OPL files (56,953 of 72,734). It was once required to initialize problem output, but DOCUMENT() now handles all initialization. If you copy a problem that includes TEXT(beginproblem()), simply delete that line.

    # Legacy (found in most OPL files)
    # DOCUMENT();
    # TEXT(beginproblem());
    
    # Modern (just DOCUMENT is enough)
    DOCUMENT();
    

    PGchoicemacros.pl: widely used, mostly deprecated

    PGchoicemacros.pl appears in over 1,000 OPL files, but most of its utility functions are now deprecated. If you copy a problem that loads PGchoicemacros.pl, check which functions it actually uses and consider whether a modern replacement exists.

    PGchoicemacros.pl: widely used, mostly deprecated reference.
    Deprecated function Replacement Example rewrite
    NchooseK(5, 3) random_subset() @pick = random_subset(3, 0..4);
    shuffle(5) random_subset() @perm = random_subset(5, 0..4);
    new_match_list PopUp widgets Build PopUp objects and use PGML inline blanks (see Matching).
    new_select_list RadioButtons Use parserRadioButtons.pl with PGML (see Multiple Choice).
    new_multiple_choice RadioButtons Use parserRadioButtons.pl with PGML (see Multiple Choice).

    Not deprecated: PGsort is sometimes confused with PGchoicemacros.pl but is actually a core function from PGbasicmacros.pl (loaded via PGstandard.pl). It does not require loading PGchoicemacros.pl and is not deprecated.

    Apply it today

    • When you copy an older example, rewrite the text block into PGML first.
    • Keep the macro list short and focused on what the prompt actually uses.
    • Use seeds to reproduce any unexpected grading or formatting behavior (see Common Mistakes and How to Fix Them for common mistakes).

    Next, depending on what you are doing:


    This page titled 2.6: Legacy PG and deprecated patterns was last modified on Fri, 27 Feb 2026 15:11:18 GMT and is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Neil R. Voss.