2.3 How to Design Programs Teaching Languages
Five of DrRacket’s languages are specifically designed for teaching:
The Beginning Student language is a small version of Racket that is tailored for beginning computer science students.
The Beginning Student with List Abbreviations languages is an extension to Beginning Student that prints lists with list instead of cons, and accepts quasiquoted input.
The Intermediate Student language adds local bindings and higher-order functions.
The Intermediate Student with Lambda language adds anonymous functions.
The teaching languages are different from conventional Racket in a number of ways:
Case-sensitive identifiers and symbols —
In a case-sensitive language, the variable names x and X are distinct, and the symbols 'x and 'X are also distinct. In a case-insensitive language, x and X are equivalent and 'x and 'X represent the same value. The teaching languages are case-sensitive by default, and other languages are usually case-insensitive. Case-sensitivity can be adjusted through the detail section of the language-selection dialog.
All numbers are exact unless #i is specified —
In the Beginning Student through Intermediate Student with Lambda languages, numbers containing a decimal point are interpreted as exact numbers. This interpretation allows students to use familiar decimal notation without inadvertently triggering inexact arithmetic. Exact numbers with decimal representations are also printed in decimal. Inexact inputs and results are explicitly marked with #i.
Procedures must take at least one argument —
In the Beginning Student through Intermediate Student languages, defined procedures must consume at least one argument. Since the languages have no side-effects, zero-argument functions are not useful, and rejecting such function definitions helps detect confusing syntactic mistakes.
Identifier required at function call position —
In the Beginning Student through Intermediate Student languages, procedure calls must be of the form (identifier ...). This restriction helps detect confusing misuses of parentheses, such as (1) or ((+ 3 4)), which is a common mistake among beginners who are used to the optional parentheses of algebra.
Top-level required at function call position —
In the Beginning Student languages, procedure calls must be of the form (top-level-identifier ...), and the number of actual arguments must match the number of formal arguments if top-level-identifier is defined. This restriction helps detect confusing misuses of parentheses, such as (x) where x is a function argument. DrRacket can detect such mistakes syntactically because Beginning Student does not support higher-order procedures.
Primitive and defined functions allowed only in function call position —
In Beginning Student languages, the name of a primitive operator or of a defined function can be used only after the open-parenthesis of a function call (except where teachpack extensions allow otherwise, as in the convert-gui teachpack). Incorrect uses of primitives trigger a syntax error. Incorrect uses of defined names trigger a run-time error. DrRacket can detect such mistakes because Beginning Student does not support higher-order procedures.
lambda allowed only in definitions —
In the Beginning Student through Intermediate Student languages, lambda (or case-lambda) may appear only in a definition, and only as the value of the defined variable.
Free variables are not allowed —
In the Beginning Student through Advanced Student languages, every variable referenced in the definitions window must be defined, pre-defined, or the name of a local function argument.
quote works only on symbols, quasiquote disallowed —
In the Beginning Student language, quote and ’ can specify only symbols. This restriction avoids the need to explain to beginners why 1 and '1 are equivalent in standard Racket. In addition, quasiquote, `, unquote, ,, unquote-splicing, and ,@ are disallowed.
Unmatched cond/case is an error —
In the Beginning Student through Advanced Student languages, falling through a cond or case expression without matching a clause signals a run-time error. This convention helps detect syntactic and logical errors in programs.
Conditional values must be true or false —
In the Beginning Student through Advanced Student languages, an expression whose value is treated as a boolean must return an actual boolean, true or false. This restriction, which applies to if, cond, and, or, nand, and nor expressions, helps detect errors where a boolean function application is omitted.
+, *, and / take at least two arguments —
In the Beginning Student through Advanced Student languages, mathematical operators that are infix in algebra notation require at least two arguments in DrRacket. This restriction helps detect missing arguments to an operator.
and, or, nand, and nor require at least 2 expressions —
In the Beginning Student through Advanced Student languages, the boolean combination forms require at least two sub-expressions. This restriction helps detect missing or ill-formed sub-expressions in a boolean expression.
set! disallowed on arguments —
In the Advanced Student language, set! cannot be used to mutate variables bound by lambda. This restriction ensures that the substitution model of function application is consistent with DrRacket’s evaluation.
Improper lists disallowed —
A proper list is either an empty list or a list created by consing onto a proper list. In the Beginning Student through Advanced Student languages, cons constructs only proper lists, signaling an error if the second argument is not a proper list. Since beginning students do not need improper lists, this restriction help detect logical errors in recursive functions.
Dot is disallowed —
In the Beginning Student through Advanced Student languages, a delimited period . is disallowed, (e.g., as an improper-list constructor in a quoted form, or for defining multi-arity procedures).
Syntactic form names disallowed as variable names —
In the Beginning Student through Advanced Student languages, all syntactic form names are keywords that cannot be used as variable names.
Re-definitions are disallowed —
In the Beginning Student through Advanced Student languages, top-level names can never be re-defined.
Function definitions are allowed only in the definitions window —
In the Beginning Student languages, function definitions are not allowed in the interactions window.
The teaching languages also deviate from traditional Racket in printing values. Different printing formats can be selected for any language through the detail section of language-selection dialog.
Constructor-style output —
See Output Printing Styles.
Quasiquote-style output —
See Output Printing Styles.
Rational number printing – In the teaching languages, all numbers that have a finite decimal expansion are printed in decimal form. For those numbers that do not have a finite decimal expansion (such as 4/3) DrRacket offers a choice. It either prints them as mixed fractions or as repeating decimals, where the repeating portion of the decimal expansion is shown with an overbar. In addition, DrRacket only shows the first 25 digits of the number’s decimal expansion. If there are more digits, the number appears with an ellipses at the end. Click the ellipses to see the next 25 digits of the expansion.
This setting controls only the initial display of a number. Right-clicking or Control-clicking (Mac OS X) on the number lets you change from the fraction representation to the decimal representation.
Show sharing in values —
Prints interaction results using the shared syntax, which exposes shared structure within a value. For example, the list created by (let ([lt (list 0)]) (list lt lt)) prints as
A program in the teaching languages should be tested using the check forms —
Tests can be disabled if necessary, see Racket for details.
One final difference between these teaching languages and other languages is the way they save files. That is, when DrRacket saves a file and the current language is one of these five teaching languages, it inserts three lines of metadata that record the precise language (including any options set) and the teachpacks. This has two benefits: opening the file later restores the settings and the metadata is formulated in such a way as to be executable code so running racket or gracket on the file in a shell will run the program in the appropriate language.
This meta data always consists of exactly three lines, and so can be stripped out by three calls to read-line.