home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-11-24 | 46.8 KB | 1,911 lines |
- .\" Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984.
- .St 6 "EXPRESSIONS, TARGETS AND TESTS"
- .Se 3 6.1 EXPRESSIONS
- .Xx scratch-pad copy
- .Xx compound
- .Tx
- In \*B, the evaluation of an expression cannot alter the values of targets
- that currently exist, nor can it create new targets that survive the expression.
- If an expression appears to alter a target, it effectively modifies
- a local ``scratch-pad''
- \fIcopy\fP of that target, and the change is invisible outside the expression.
- .Sy 3
- .Pr expression 4
- .Al
- single-expression
- .Al
- multiple-expression
- .Pr single-expression 3
- .Al
- basic-expression
- .Al
- \*(<:(\*(:> expression \*(<:)\*(:>
- .Pr basic-expression 3
- .Al
- simple-expression
- .Al
- formula
- .Pr simple-expression 7
- .Al
- constant
- .Al
- target-content
- .Al
- trimmed-text
- .Al
- table-selection
- .Al
- display
- .Al
- refined-expression
- .Pr tight-expression 3
- .Al
- simple-expression
- .Al
- zeroadic-formula
- .Al
- \*(<:(\*(:> expression \*(<:)\*(:>
- .Pr right-expression 3
- .Al
- tight-expression
- .Al
- monadic-formula
- .Eo 6 basic-:\0\0\k2simple-:\0\k3tight-:\0\0\0\0\k4right-expressions:
- \h'|\n1u'\*(<:a\*(:> \h'|\n2u'\*(<:a\*(:> \h'|\n3u'\*(<:a\*(:> \h'|\n4u'\*(<:a\*(:>
- \h'|\n1u'\*(<:-a\*(:> \h'|\n4u'\*(<:-a\*(:>
- \h'|\n1u'\*(<:a+b\*(:>
- \h'|\n3u'\*(<:(a+b)\*(:> \h'|\n4u'\*(<:(a+b)\*(:>
- .Xe
- .Tx
- The various kinds of expressions that are distinguished here
- serve to define the syntax
- in such a way that no parentheses are needed where the meaning is
- sufficiently clear.
- .Pr multiple-expression 1
- .Al
- single-expression\*(<:,\*(:> single-expression
- .Al
- single-expression\*(<:,\*(:> multiple-expression
- .Ex 3
- \k1multiple-expressions:
- \h'|\n1u'\*(<:1, 'abc'\*(:>
- \h'|\n1u'\*(<:(1, 0), (0, 1), (-1, 0), (0, -1)\*(:>
- .Xe
- .Tx
- The value of a multiple-expression composed of single-expressions
- separated by commas
- is the compound whose fields are the values of the
- successive single-expressions.
- .Se 3 6.1.1 NUMERIC-CONSTANTS
- .Sy 3
- .Pr numeric-constant 3
- .Al
- exact-constant
- .Al
- approximate-constant
- .Pr exact-constant 3
- .Al
- integral-part\0optional-fractional-part
- .Al
- integral-part \*(<:.\*(:>
- .Al
- fractional-part
- .Pr integral-part 3
- .Al
- digit
- .Al
- integral-part\0digit
- .Pr digit 2
- .Al
- \*(<:0\*(:>
- .Al
- \*(<:1\*(:>
- .Al
- \*(<:2\*(:>
- .Al
- \*(<:3\*(:>
- .Al
- \*(<:4\*(:>
- .Al
- \*(<:5\*(:>
- .Al
- \*(<:6\*(:>
- .Al
- \*(<:7\*(:>
- .Al
- \*(<:8\*(:>
- .Al
- \*(<:9\*(:>
- .Pr fractional-part 3
- .Al
- \&\*(<:.\*(:> digit
- .Al
- fractional-part\0digit
- .Pr approximate-constant 2
- .Sl
- exact-constant\0exponent-part
- .Pr exponent-part 2
- .Sl
- \*(<:E\*(:> optional-plusminus\0integral-part
- .Pr plusminus 2
- .Al
- \*(<:+\*(:>
- .Al
- \*(<:-\*(:>
- .Eo 5 exact-constants:\0\0\0\0\0\0\k2approximate-constants:
- \h'|\n1u'\*(<:666\*(:> \h'|\n2u'\*(<:2.99793E8\*(:>
- \h'|\n1u'\*(<:666.\*(:> \h'|\n2u'\*(<:2.99793E+8\*(:>
- \h'|\n1u'\*(<:3.14\*(:> \h'|\n2u'\*(<:1E-9\*(:>
- .Xe
- .Tx
- The value of an exact-constant is an exact number.
- For example, \*(<:1.25\*(:> stands for the exact number \*(<:5/4\*(:>.
- The value of an approximate-constant is an approximate number.
- The exponent-part gives the power of ten in floating-point notation.
- For example, \*(<:1.2345E2\*(:> and \*(<:~123.45\*(:> are (approximately) the same,
- because \*(<:123.45 = 1.2345*10**2\*(:>.
- .Se 2 6.1.2 TARGET-CONTENTS
- .Sy 2
- .Pr target-content 2
- .Sl
- tag
- .Tx
- The value of a target-content is the value last put in the target whose
- name is the given tag.
- .Se 2 6.1.3 TRIMMED-TEXTS
- .Xx integer
- .Sy 2
- .Pr trimmed-text 2
- .Al
- tight-expression \*(<:@\*(:> right-expression
- .Al
- tight-expression \*(<:|\*(:> right-expression
- .Ps
- .Ex 6
- \k1trimmed-texts:
- \h'|\n1u'\*(<:t@p\*(:>
- \h'|\n1u'\*(<:t|1\*(:>
- \h'|\n1u'\*(<:t|q@p\*(:>
- \h'|\n1u'\*(<:t@p|(q-p+1)\*(:>
- .Xe
- .Tx
- The value of the tight-expression must be a text T, and that
- of the right-expression must be an integer N.
- .br
- If the sign between the expressions is \*(<:@\*(:>, then the value of
- the trimmed-text is that of T after removing the first N\(mi1 characters.
- For example, \*(<:'lamplight'@4 = 'plight'\*(:>.
- N must be at least 1 and at most one more than the length of T.
- .br
- If the sign between the expressions is \*(<:|\*(:>, then the value of
- the trimmed-text is the text consisting of the first N characters of T.
- For example, \*(<:'scarface'|5 = 'scarf'\*(:>.
- N must be at least 0 and at most equal to the length of T.
- .br
- Note that the tight-expression itself may be a trimmed-text
- again.
- For example, \*(<:'department'|6@3 = 'depart'@3 = 'part'\*(:>.
- .Se 3 6.1.4 TABLE-SELECTIONS
- .Xx key
- .Xx associate
- .Xx table entry
- .Sy 3
- .Pr table-selection 3
- .Sl
- tight-expression \*(<:[\*(:> expression \*(<:]\*(:>
- .Sx 2 table-selection:
- \*(<:t[i, j]\*(:>
- .Xe
- .Tx
- The value of the tight-expression must be a table T, and
- the value of the expression between the square brackets must
- be a key K of T.
- The value of the table-selection is then the associate of
- the table entry in T whose key is K.
- .Se 3 6.1.5 DISPLAYS
- .Xx integer
- .Xx character
- .Xx quote
- .Xx convert to a text
- .Xx ambiguity
- .Xx empty list
- .Xx empty table
- .Xx key
- .Xx associate
- .Sy 3
- .Pr display 4
- .Al
- text-display
- .Al
- list-display
- .Al
- table-display
- .Pr text-display 3
- .Al
- \&\*(<:'\*(:> optional-text-body \*(<:'\*(:>
- .Al
- \*(<:"\*(:> optional-text-body \*(<:"\*(:>
- .Ps
- The text-displays \*(<:''\*(:> and \*(<:""\*(:> stand for the empty text.
- A text-body may be any sequence of printable characters
- (see section 1 under `Texts')
- and conversions
- (see below).
- However, in a text-display in the \*(<:'\*(:>\^...\^\*(<:'\*(:> style,
- any single quote \*(<:'\*(:> in the text must be written twice to give \*(<:''\*(:>.
- Otherwise, it will signal the end of the text-display.
- Similarly, in a text-display in the \*(<:"\*(:>\^...\^\*(<:"\*(:> style,
- any double quote \*(<:"\*(:> in the text must be written twice to give \*(<:""\*(:>.
- Finally, the back-quote \*(<:`\*(:> must be written twice too, giving \*(<:``\*(:>.
- Otherwise, it signals a conversion.
- .Pr conversion 2
- .Sl
- \*(<:`\*(:> expression \*(<:`\*(:>
- .Ps
- The requirement that some signs be written twice does not hold
- \fIinside\fP a conversion.
- For example, \*(<:'`t['a']`'\*(:> is proper, whereas \*(<:'`t[''a'']`'\*(:> is not.
- .Eo 6 text-displays:
- \h'|\n1u'\*(<:''\*(:>
- \h'|\n1u'\*(<:'He said: "Don''t!"'\*(:>
- \h'|\n1u'\*(<:"He said: ""Don't!"""\*(:>
- \h'|\n1u'\*(<:'altitude is `a/1E3` km'\*(:>
- .Xe
- .Tx
- The value of a text-display is the text composed of the
- characters given between the enclosing text quotes.
- If the text-display contains conversions, the expressions of
- these conversions are evaluated first and converted to a
- text in the same way as for a write-command.
- For example,
- since
- .Di 1
- \*(<:WRITE 239*4649\*(:>
- .Ed
- causes the text \*(<:1111111\*(:> to be written,
- the text-display
- .Di 1
- \&\*(<:'239 times 4649 gives `239*4649`'\*(:>
- .Ed
- is equivalent to
- .Di 1
- \&\*(<:'239 times 4649 gives 1111111'\*(:>.
- .Ed
- The quotes and conversion-signs that had to be written twice
- according to the above rules correspond to one character of
- the resulting text.
- For example, the number of characters in \*(<:'x''y""z'\*(:> is 6,
- because it consists of one \*(<:x\*(:>, \fIone\fP \*(<:'\*(:> character,
- one \*(<:y\*(:>, \fItwo\fP \*(<:"\*(:> characters, and finally one \*(<:z\*(:>.
- Another way to specify the same text is \*(<:"x'y""""z"\*(:>.
- .Pr list-display 2
- .Sl
- \*(<:{\*(:> optional-list-body \*(<:}\*(:>
- .Pr list-body 5
- .Al
- list-filler-series
- .Al
- single-expression \*(<:..\*(:> single-expression
- .Ps
- The ambiguity in, e.g., \*(<:{1...9}\*(:>, is resolved by parsing it
- as \*(<:{1. .. 9}\*(:>.
- .Pr list-filler-series 2
- .Al
- list-filler
- .Al
- list-filler\*(<:;\*(:> list-filler-series
- .Pr list-filler 2
- .Sl
- single-expression
- .Eo 6 list-displays:
- \h'|\n1u'\*(<:{}\*(:>
- \h'|\n1u'\*(<:{x1; x2; x3}\*(:>
- \h'|\n1u'\*(<:{1..n-1}\*(:>
- \h'|\n1u'\*(<:{'a'..'z'}\*(:>
- .Xe
- .Tx
- The value of \*(<:{}\*(:> is an empty list.
- (It may also be an empty table; see below.)
- .br
- The value of a list-display containing list-fillers is the
- list whose entries are the values of those list-fillers.
- If values occur multiply, they give rise to multiple entries
- in the list.
- .br
- For a list-display of the form \*(<:{\*(:>p\*(<:..\*(:>q\*(<:}\*(:>, p and q must both be
- integers, or both be characters (texts of length one).
- The resulting value is then the list of all integers
- or characters x such that p\ \(<= x\ \(<=\ q.
- For example, \*(<:{1..4} = {1; 2; 3; 4}\*(:> and \*(<:{'a'..'c'} = {'a'; 'b'; 'c'}\*(:>.
- .br
- If p\ >\ q, the list is empty, but this is only allowed if p
- and q are adjacent.
- If there is an intervening integer or character x (such that
- p\ >\ x\ >\ q), an error is reported.
- .Pr table-display 2
- .Sl
- \*(<:{\*(:> optional-table-filler-series \*(<:}\*(:>
- .Pr table-filler-series 2
- .Al
- table-filler
- .Al
- table-filler\*(<:;\*(:> table-filler-series
- .Pr table-filler 2
- .Sl
- \*(<:[\*(:> expression \*(<:] :\*(:> single-expression
- .Eo 6 table-displays:
- \h'|\n1u'\*(<:{}\*(:>
- \h'|\n1u'\*(<:{[i, j]: 0}\*(:>
- \h'|\n1u'\*(<:{[0]: {}; [1]: {0}}\*(:>
- \h'|\n1u'\*(<:{[name]: (month, day, year)}\*(:>
- .Xe
- .Tx
- The table-display \*(<:{}\*(:> stands for an empty table.
- Otherwise, each table-filler gives a table entry with key K
- and associate A, where K is the value of the expression
- between square brackets, and A is the value of the
- single-expression following the colon.
- The result is then the table containing these table
- entries.
- .br
- If there are \fIdifferent\fP table entries with the same
- key, an error is reported.
- Multiple occurrences of the \fIsame\fP table entry, however,
- are allowed.
- The extra occurrences are then simply discarded.
- .Se 2 6.1.6 FORMULAS
- .Xx formula
- .Xx function
- .Xx ambiguity
- .Xx parentheses
- .Xx brackets
- .Xx priority
- .Xx user-defined-function
- .Xx yield-unit
- .Xx target
- .Xx scratch-pad copy
- .Xx local
- .Xx return-command
- .Xx predefined functions
- .Xx number
- .Xx denominator
- .Xx numerator
- .Xx text
- .Xx convert to a text
- .Xx text, list and table
- .Xx key
- .Xx character
- .Xx associate
- .Xx list entry
- .Xx integer
- .Sy 2
- .Pr zeroadic-formula 2
- .Sl
- zeroadic-function
- .Pr monadic-formula 2
- .Sl
- monadic-function\0actual-operand
- .Pr dyadic-formula 2
- .Al
- actual-operand\0dyadic-function\0actual-operand
- .Ps
- The parsing ambiguities introduced by these rules
- are resolved by priority rules, as follows:
- .in +\w'2.\ 'u
- .ti -\w'2.\ 'u
- 1.\ If there is no parsing ambiguity (as in \*(<:1 + sin x\*(:>),
- no parentheses are needed.
- .ti -\w'2.\ 'u
- 2.\ If the order makes no difference (as in \*(<:a*b*c\*(:>, \*(<:a*b/c\*(:> or
- \*(<:a^b^c\*(:>), no parentheses are needed.
- .ti -\w'2.\ 'u
- 3.\ The five arithmetic functions
- \*(<:**\*(:>, \*(<:*\*(:>, \*(<:/\*(:>, \*(<:+\*(:> and \*(<:-\*(:>
- have their traditional priority rules:
- .in +4
- \*(<:**\*(:> comes before \*(<:*\*(:>, \*(<:/\*(:>, \*(<:+\*(:> and \*(<:-\*(:>;
- .br
- \*(<:*\*(:> and \*(<:/\*(:> come before \*(<:+\*(:> and \*(<:-\*(:>;
- .br
- combinations of \*(<:+\*(:> and \*(<:-\*(:> are computed from left to right.
- .in -4
- Note, however, that \*(<:a**b**c\*(:>, \*(<:a/b*c\*(:> and \*(<:a/b/c\*(:> are wrong.
- .ti -\w'2.\ 'u
- 4.\ The function \*(<:#\*(:> has a high priority, higher than the
- five arithmetic functions, and the function \*(<:~\*(:> has a
- higher priority than all other functions.
- .ti -\w'2.\ 'u
- 5.\ All other functions,
- in particular \*(<:^\*(:>, \*(<:^^\*(:>, \*(<:<<\*(:>, \*(<:><\*(:>, \*(<:>>\*(:>
- and all tags (like \*(<:sin\*(:> or \*(<:floor\*(:>) have no established priority and
- may be used
- .in +4
- .ti -\w'\(em\ 'u
- \(em\ having formulas as operands only if these operands
- are parenthesized (except as in, e.g., \*(<:exp -x\*(:>, because of
- point 1 above, or as in \*(<:~1>>20\*(:> because of point 4);
- .ti -\w'\(em\ 'u
- \(em\ in operands of other formulas only if these operands are
- parenthesized (except as above).
- .in -4
- .in -\w'2.\ 'u
- .Bl 3
- None of
- \*(<:a/b/c\*(:>, \*(<:a/b*c\*(:> and \*(<:sin x+y\*(:>
- is a correct formula.
- Each of these can be made correct by inserting parentheses,
- depending on the intention:
- either \*(<:(a/b)/c\*(:> or \*(<:a/(b/c)\*(:>,
- either \*(<:(a/b)*c\*(:> or \*(<:a/(b*c)\*(:>,
- and either \*(<:(sin x) + y\*(:> or \*(<:sin(x+y)\*(:>.
- Note that because of point 5 above
- \*(<:sin(x)+1\*(:> is just as wrong as \*(<:sin x + 1\*(:>,
- in spite of what other programming languages might lead you to expect.
- .br
- The function \*(<:#\*(:> has been given
- a high priority since expressions like \*(<:#t+1\*(:> are so common,
- that it would be a nuisance to have to parenthesize these,
- and more so since \*(<:#(t+1)\*(:> is meaningless anyway.
- The reason for the high priority of the function \*(<:~\*(:> is
- to make
- \*(<:~0\*(:>, for example, for all practical purposes behave as a constant.
- .Pr zeroadic-function 2
- .Sl
- tag
- .Pr monadic-function 6
- .Al
- \*(<:~\*(:>
- .Al
- \*(<:+\*(:>
- .Al
- \*(<:-\*(:>
- .Al
- \*(<:*/\*(:>
- .Al
- \*(<:/*\*(:>
- .Al
- \*(<:#\*(:>
- .Al
- tag
- .Pr dyadic-function 3
- .Al
- \*(<:+\*(:>
- .Al
- \*(<:-\*(:>
- .Al
- \*(<:*\*(:>
- .Al
- \*(<:/\*(:>
- .Al
- \*(<:**\*(:>
- .Al
- \*(<:^\*(:>
- .Al
- \*(<:^^\*(:>
- .Al
- \*(<:<<\*(:>
- .Al
- \*(<:><\*(:>
- .Al
- \*(<:>>\*(:>
- .Al
- \*(<:#\*(:>
- .Al
- tag
- .Pr actual-operand 3
- .Sl
- single-expression
- .Eo 3 zeroadic-formula:\0\0\0\k2monadic-formula:\0\0\0\k3dyadic-formula:
- \h'|\n1u'\*(<:pi\*(:> \h'|\n2u'\*(<:atan(y/x)\*(:> \h'|\n3u'\*(<:x atan y\*(:>
- .Xe
- .Us 7 Formulas with user-defined functions
- A formula whose function is defined by a yield-unit, is
- evaluated in the following steps:
- .in \w'2.\ 'u
- .ti 0
- 1.\ A copy is made of the current environment (the value of
- all targets), and all computations during the evaluation of
- the formula will take place in this ``scratch-pad copy''.
- .ti 0
- 2.\ Any local tags in the yield-unit that might clash with tags currently
- in use are systematically replaced by other tags that do not cause conflict.
- .ti 0
- 3.\ Each actual-operand is evaluated and put in the
- corresponding formal-operand, used as a (new)
- target.
- .ti 0
- 4.\ The command-suite of the unit, thus modified, is executed.
- .in 0
- The evaluation of the formula is complete when the execution
- of this command-suite terminates because of the execution of a return-command;
- the value of the formula is the value returned.
- .Us 7 Formulas with predefined functions
- .de Qr
- .sp 1
- .in 0
- .ne 3
- ..
- .de Qe
- .br
- .sp -1
- .in 7m
- ..
- .Us 0 A. Functions on numbers
- .Qr
- \*(<:~x\*(:>
- .Qe
- returns an approximate number, as close as possible
- in arithmetic magnitude to \*(<:x\*(:>.
- .Qr
- \*(<:x+y\*(:>
- .Qe
- returns the sum of \*(<:x\*(:> and \*(<:y\*(:>.
- The result is exact if both operands are exact.
- .Qr
- \*(<:+x\*(:>
- .Qe
- returns the value of \*(<:x\*(:>.
- .Qr
- \*(<:x-y\*(:>
- .Qe
- returns the difference of \*(<:x\*(:> and \*(<:y\*(:>.
- The result is exact if both operands are exact.
- .Qr
- \*(<:-x\*(:>
- .Qe
- returns minus the value of \*(<:x\*(:>.
- The result is exact if the operand is exact.
- .Qr
- \*(<:x*y\*(:>
- .Qe
- returns the product of \*(<:x\*(:> and \*(<:y\*(:>.
- The result is exact if both operands are exact.
- .Qr
- \*(<:x/y\*(:>
- .Qe
- returns the quotient of \*(<:x\*(:> and \*(<:y\*(:>.
- The value of \*(<:y\*(:> must not be zero.
- The result is exact if both operands are exact.
- .Qr
- \*(<:x**y\*(:>
- .Qe
- returns \*(<:x\*(:> to the power \*(<:y\*(:>.
- The result is exact if \*(<:x\*(:> is exact and \*(<:y\*(:> is an integer.
- If \*(<:x\*(:> is negative,
- \*(<:y\*(:> must be an integer or an exact number with an odd denominator.
- If \*(<:x\*(:> is zero,
- \*(<:y\*(:> must not be negative.
- If \*(<:y\*(:> is zero, the result is one (exact or approximate).
- .Qr
- \*(<:n root x\*(:>
- .Qe
- returns the same as \*(<:x**(1/n)\*(:>.
- .Qr
- \*(<:root x\*(:>
- .Qe
- returns the same as \*(<:2 root x\*(:>, the square root of \*(<:x\*(:>.
- .Qr
- \*(<:abs x\*(:>
- .Qe
- returns the absolute value of \*(<:x\*(:>.
- The result is exact if the operand is exact.
- .Qr
- \*(<:sign x\*(:>
- .Qe
- returns \(mi1 if \*(<:x\*(:> is negative, 0 if \*(<:x\*(:> is zero, and 1 otherwise.
- .Qr
- \*(<:floor x\*(:>
- .Qe
- returns the largest integer not exceeding \*(<:x\*(:> in arithmetic
- magnitude.
- .Qr
- \*(<:ceiling x\*(:>
- .Qe
- returns the same as \*(<:- floor -x\*(:>.
- .Qr
- \*(<:n round x\*(:>
- .Qe
- returns the same as \*(<:(10**-n)*floor(x*10**n+.5)\*(:>.
- For example, \*(<:4 round pi = 3.1416\*(:>.
- The value of \*(<:n\*(:> must be an integer.
- It may be negative: \*(<:(-2) round 666 = 700\*(:>.
- .Qr
- \*(<:round x\*(:>
- .Qe
- returns the same as \*(<:0 round x\*(:>.
- .Qr
- \*(<:a mod n\*(:>
- .Qe
- returns the same as \*(<:a-n*floor(a/n)\*(:>,
- that is, the remainder after dividing \*(<:a\*(:> by \*(<:n\*(:>.
- (Both operands may be approximate, and \*(<:n\*(:> may be negative, but not zero.)
- .Qr
- \*(<:/*x\*(:>
- .Qe
- returns the ``denominator'' of \*(<:x\*(:>,
- that is, regarding \*(<:x\*(:> as the fraction \*(<:p/q\*(:>,
- the smallest positive integer \*(<:q\*(:> such that \*(<:q*x\*(:> is an integer.
- The value of \*(<:x\*(:> must be an exact number.
- .Qr
- \*(<:*/x\*(:>
- .Qe
- returns the corresponding ``numerator'' with the same sign as \*(<:x\*(:>,
- the same integer as \*(<:(/*x)*x\*(:>.
- So, if \*(<:x\*(:> is exact, \*(<:x = (*/x)/(/*x)\*(:>.
- .Qr
- \*(<:pi\*(:>
- .Qe
- returns approximately \*(<:3.1415926535\*(:>...
- .Qr
- \*(<:sin x\*(:>
- .Qe
- returns an approximate number by applying the sine function to \*(<:x\*(:>,
- with \*(<:x\*(:> in radians.
- .Qr
- \*(<:cos x\*(:>
- .Qe
- returns an approximate number by applying the cosine function to \*(<:x\*(:>,
- with \*(<:x\*(:> in radians.
- .Qr
- \*(<:tan x\*(:>
- .Qe
- returns the same as \*(<:(sin x) / (cos x)\*(:>.
- .Qr
- \*(<:x atan y\*(:>
- .Qe
- returns an approximate number \*(<:phi\*(:>, in the range from (about)
- \*(<:-pi\*(:> to \*(<:+pi\*(:>, such that
- \*(<:x\*(:> is approximated by \*(<:r * cos phi\*(:>
- and \*(<:y\*(:> by \*(<:r * sin phi\*(:>, where \*(<:r = root(x*x+y*y)\*(:>.
- The operands must not both be zero.
- .Qr
- \*(<:atan x\*(:>
- .Qe
- returns the same as \*(<:1 atan x\*(:>.
- .Qr
- \*(<:e\*(:>
- .Qe
- returns approximately \*(<:2.7182818284\*(:>...
- .Qr
- \*(<:exp x\*(:>
- .Qe
- returns approximately the same as \*(<:e**x\*(:>.
- .Qr
- \*(<:log x\*(:>
- .Qe
- returns an approximate number by applying the natural logarithm function
- (with base \*(<:e\*(:>)
- to \*(<:x\*(:>.
- The value of \*(<:x\*(:> must be positive.
- .Qr
- \*(<:b log x\*(:>
- .Qe
- returns the same as \*(<:(log x) / (log b)\*(:>,
- that is, the logarithm with base \*(<:b\*(:> of \*(<:x\*(:>.
- .Us 7 B. Functions on texts
- .Qr
- \*(<:t^u\*(:>
- .Qe
- returns the text consisting of \*(<:t\*(:> and \*(<:u\*(:> joined.
- For example, \*(<:'now'^'here' = 'nowhere'\*(:>.
- .Qr
- \*(<:t^^n\*(:>
- .Qe
- returns the text consisting of \*(<:n\*(:> copies of \*(<:t\*(:> joined together.
- For \pexample, \*(<:'Fi! '^^3 = 'Fi! Fi! Fi! '\*(:>.
- The value of \*(<:n\*(:> must be an integer and not negative.
- .Qr
- \*(<:x<<n\*(:>
- .Qe
- converts \*(<:x\*(:> to a text and adds space characters to
- the right until the length is \*(<:n\*(:>.
- For example, \*(<:123<<6 = '123 '\*(:>.
- In no case is the text truncated; if \*(<:n\*(:> is too small,
- the resulting text is as long as necessary.
- The value of \*(<:n\*(:> must be an integer, but \*(<:x\*(:> may be of any type.
- See write-commands, section 5.1.2, for details about converting values to
- texts.
- .Qr
- \*(<:x><n\*(:>
- .Qe
- converts \*(<:x\*(:> to a text and adds space characters to
- the right and to the left, in turn, until the length is \*(<:n\*(:>.
- For example, \*(<:123><6 = ' 123 '\*(:>.
- In no case is the text truncated.
- The value of \*(<:n\*(:> must be an integer, but \*(<:x\*(:> may be of any type.
- .Qr
- \*(<:x>>n\*(:>
- .Qe
- converts \*(<:x\*(:> to a text and adds space characters to
- the left until the length is \*(<:n\*(:>.
- For example, \*(<:123>>6 = ' 123'\*(:>.
- In no case is the text truncated.
- The value of \*(<:n\*(:> must be an integer, but \*(<:x\*(:> may be of any type.
- .Bl 7
- .Us 7 C. Functions on texts, lists and tables
- .Qr
- \*(<:keys t\*(:>
- .Qe
- requires a table as operand, and returns a list of all keys
- in the table.
- For example, \*(<:keys {[1]: 1; [4]: 2; [9]: 3} = {1; 4; 9}\*(:>.
- .Qr
- \*(<:#t\*(:>
- .Qe
- accepts texts, lists and tables.
- For a text operand, its length is returned, and
- for a list or table operand, the number of
- entries is returned (where duplicates in lists are counted).
- .Qr
- \*(<:e#t\*(:>
- .Qe
- accepts texts, lists and tables for the right operand.
- .br
- For a text operand, the first operand must
- be a character, and the number of times the character
- occurs in the text is returned.
- For example, \*(<:'i'#'mississippi' = 4\*(:>.
- .br
- For a list operand, the number of entries is returned
- that are equal to the first operand
- (which must be of the same type as the list entries.)
- .br
- For example, \*(<:3#{1; 3; 3; 4} = 2\*(:>.
- .br
- .??
- For a table operand, the number of \fIassociates\fP is returned
- that are equal to the first operand
- (which must be of the same type as the associates in the table.)
- For example, \*(<:3#{[1]: 3; [2]: 4; [3]: 3} = 2\*(:>.
- .Qr
- \*(<:min t\*(:>
- .Qe
- accepts texts, lists and tables.
- For a text operand, its smallest (in the ASCII order) character is returned,
- for a list operand, its smallest
- entry is returned, and
- for a table operand, its smallest
- \fIassociate\fP
- .??
- is returned.
- For example, \*(<:min 'uscule' = 'c'\*(:>,
- \*(<:min{1; 3; 3; 4} = 1\*(:>, and
- \*(<:min{[1]: 3; [2]: 4; [3]: 3} = 3\*(:>.
- The text, list or table must not be empty.
- .br
- To get the smallest \fIkey\fP of a table \*(<:t\*(:>,
- use \*(<:min keys t\*(:>.
- .Qr
- \*(<:e min t\*(:>
- .Qe
- accepts texts, lists and tables for the right operand.
- .br
- For a text operand,
- the first operand
- must
- be a character, and the smallest character in the text
- \fIexceeding\fP
- that character is returned.
- For example, \*(<:'i' min 'mississippi' = 'm'\*(:>.
- .br
- For a list operand, the smallest
- entry is returned exceeding the first operand
- (which must be of the same type as the list entries.)
- For example, \*(<:3 min {1; 3; 3; 4} = 4\*(:>.
- .br
- For a table operand, the smallest associate
- is returned exceeding the first operand
- (which must be of the same type as the associates in the table.)
- For example, \*(<:3 min {[1]: 3; [2]: 4; [3]: 3} = 4\*(:>.
- .br
- There must be a character, list entry or table associate exceeding
- the first operand.
- .Qr
- \*(<:max t\*(:> and
- .br
- \*(<:e max t\*(:>
- .Qe
- .Qe
- are like \*(<:min\*(:>, except that they return the largest
- element, and in the dyadic case the largest element
- that is less than the first operand.
- For example, \*(<:'m' max 'mississippi' = 'i'\*(:>.
- .Qr
- \*(<:n th'of t\*(:>
- .Qe
- requires an integer in \*(<:{1..#t}\*(:> for the left operand, and
- accepts texts, lists and tables for the right operand.
- It returns the \*(<:n\*(:>'th character, list entry or associate.
- .br
- In fact, \*(<:n th'of t\*(:>, for a text \*(<:t\*(:>, is written as easily
- \*(<:t@n|1\*(:>.
- For a table, it is the same as \*(<:t[n th'of (keys t)]\*(:>,
- which is something different from \*(<:t[n]\*(:>, unless,
- of course, \*(<:keys t = {1..#t}\*(:>.
- For a list,
- \*(<:1 th'of t\*(:> is \*(<:min t\*(:>.
- .Se 2 6.1.7 REFINED-EXPRESSIONS
- .Xx expression-refinement
- .Xx scratch-pad copy
- .Xx return-command
- .Sy 2
- .Pr refined-expression 2
- .Sl
- tag
- .Ps
- The tag of a refined-expression must occur as
- the tag of one
- expression-refinement in the unit
- in which it occurs.
- .Sx 3 \k1refined-expression:
- \*(<:stack'pointer\*(:>
- .Xe
- .Tx
- A refined-expression is
- evaluated in the following steps:
- .in \w'2.\ 'u
- .ti 0
- 1.\ A copy is made of the current environment (the value of
- all targets), and all computations during the evaluation of
- the expression will take place in this ``scratch-pad copy''.
- .ti 0
- 2.\ The command-suite of the corresponding
- expression-refinement is executed.
- .in 0
- The evaluation of the refined-expression is complete when the execution
- of this command-suite terminates because of the execution of a return-command;
- the value of the refined-expression is the value returned.
- .Sa
- expression-refinements (4.4).
- .Se 4 6.2 TARGETS
- .Xx compound
- .Sy 4
- .Pr target 4
- .Al
- single-target
- .Al
- multiple-target
- .Pr single-target 3
- .Al
- basic-target
- .Al
- \*(<:(\*(:> target \*(<:)\*(:>
- .Pr basic-target 4
- .Al
- tag
- .Al
- trimmed-text-target
- .Al
- table-selection-target
- .Tx
- For the use of a tag as target, see below under IDENTIFIERS.
- For other kinds of targets, see below under the appropriate heading.
- .Pr multiple-target 1
- .Al
- single-target\*(<:,\*(:> single-target
- .Al
- single-target\*(<:,\*(:> multiple-target
- .Ex 3
- \k1multiple-targets:
- \h'|\n1u'\*(<:nn, t2\*(:>
- \h'|\n1u'\*(<:(x0, y0), (x1, y1), (x2, y2), (x3, y3)\*(:>
- .Xe
- .Tx
- If a value is put in a multiple-target, the value must be
- a compound with as many fields as there are single-targets
- separated by commas in the multiple-target.
- The successive fields are then put in the
- successive single-targets.
- If it makes a difference in what order the fields are put in
- the single-targets (as in \*(<:PUT 1, 2 IN x, x\*(:>
- where the final value of \*(<:x\*(:> might be either \*(<:1\*(:> or \*(<:2\*(:>),
- an error is reported {{but this is currently not checked}}.
- .br
- Note that the meaning of \*(<:PUT a, b IN b, a\*(:>
- is well defined (provided that \*(<:a\*(:> and \*(<:b\*(:> are defined and have
- values of the same type):
- first the value of the expression \*(<:a, b\*(:> is determined,
- and that value is next put in \*(<:b, a\*(:>.
- Note also that the meaning of \*(<:PUT t[i], t[j] IN t[j], t[i]\*(:>
- is well defined, even if \*(<:i\*(:> and \*(<:j\*(:> have the same value.
- For although in this case a value is put twice in the same
- target, that value is the same each time, so the order does not matter.
- .Se 2 6.2.1 IDENTIFIERS
- .Xx tag
- .Xx target
- .Xx location
- .Xx local
- .Sy 2
- .Pr identifier 4
- .Al
- single-identifier
- .Al
- multiple-identifier
- .Pr single-identifier 3
- .Al
- tag
- .Al
- \*(<:(\*(:> identifier \*(<:)\*(:>
- .Pr multiple-identifier 1
- .Al
- single-identifier\*(<:,\*(:> single-identifier
- .Al
- single-identifier\*(<:,\*(:> multiple-identifier
- .Eo 6 identifiers:\0\0\0\0\0\0\0\0\0\0\0\k2single-identifiers:
- \h'|\n1u'\*(<:a\*(:>\h'|\n2u'\*(<:a\*(:>
- \h'|\n1u'\*(<:(a)\*(:>\h'|\n2u'\*(<:(a)\*(:>
- \h'|\n1u'\*(<:(a, b, (c, d))\*(:>\h'|\n2u'\*(<:(a, b, (c, d))\*(:>
- \h'|\n1u'\*(<:a, b, (c, d)\*(:>
- .Xe
- .Tx
- All identifiers can be used as targets, but the converse is
- not true.
- For example,
- .Di 1
- \*(<:FOR a[1] IN {1..3}: WRITE a\*(:>
- .Ed
- is wrong, because \*(<:a[1]\*(:>, although a target, is not an identifier.
- If something is put in a target that is a tag, and no
- location for that tag exists already, it is created first.
- If the location is created locally (the tag did not occur in
- an immediate command and was not listed in a share-heading),
- the location will cease to exist when the current unit is exited.
- For putting in multiple-identifiers, see multiple-targets in section 6.2.
- .Se 2 6.2.2 TRIMMED-TEXT-TARGETS
- .Sy 2
- .Pr trimmed-text-target 3
- .Al
- target \*(<:@\*(:> right-expression
- .Al
- target \*(<:|\*(:> right-expression
- .Ps\"(The \*(<:|\*(:> in the last line is not the BNF choice indicator, but should be takenliterally.)
- .Ex 6
- \k1trimmed-text-targets:
- \h'|\n1u'\*(<:t@p\*(:>
- \h'|\n1u'\*(<:t|1\*(:>
- \h'|\n1u'\*(<:t|q@p\*(:>
- \h'|\n1u'\*(<:t@p|(q-p+1)\*(:>
- .Xe
- .Tx
- The target must hold a text T, and the value
- of the right-expression must be an integer N.
- .br
- If the sign used is \*(<:@\*(:>, then the
- trimmed-text-target indicates a location consisting of the
- positions of T starting with the N'th position.
- N must be at least 1 and at most one more than the length of T.
- For example, after
- .Di 2
- \*(<:PUT 'computer' IN tt
- PUT 'ass' IN tt@5\*(:>
- .Ed
- \*(<:tt\*(:> will contain the text \*(<:'compass'\*(:>.
- .br
- If the sign used is \*(<:|\*(:>, then the
- trimmed-text-target indicates a location
- consisting of the first N characters of T.
- N must be at least 0 and at most equal to the length of T.
- For example, after
- .Di 2
- \*(<:PUT 'computer' IN tt
- PUT 'ne' IN tt|4\*(:>
- .Ed
- \*(<:tt\*(:> will contain the text \*(<:'neuter'\*(:>.
- .Bl 1
- Note that the target itself may be a trimmed-text-target
- again.
- For example, after
- .Di 2
- \*(<:PUT 'computer' IN tt
- PUT 'm' IN tt@4|1\*(:>
- .Ed
- \*(<:tt\*(:> will contain the text \*(<:'commuter'\*(:>.
- .br
- Some useful special cases: \*(<:PUT '' IN t|1\*(:>
- removes the first character of the text in \*(<:t\*(:>;
- .br
- \*(<:PUT '.' IN t@(#t+1)\*(:>
- appends a period to the text in \*(<:t\*(:>.
- .Se 2 6.2.3 TABLE-SELECTION-TARGETS
- .Xx key
- .Xx associate
- .Xx table entry
- .Xx location
- .Xx type
- .Sy 2
- .Pr table-selection-target 2
- .Sl
- target \*(<:[\*(:> expression \*(<:]\*(:>
- .Sx 3 \k1table-selection-target:
- \*(<:t[i, j]\*(:>
- .Xe
- .Tx
- The target must contain a table.
- The value of the expression is a key K, to be used as selector.
- For each key in the table, there is a location for the
- corresponding associate.
- If K is an existing key of the table, the location for the
- table-selection-target is that of the associate corresponding to K.
- If a value A is then put in the table-selection-target,
- the original associate held in that location is superseded by A.
- If K is not an existing key and a value A is to be put in the
- table-selection-target, a new location is created, and the
- (original) table is made to contain a new table entry
- consisting of K and A.
- K must be of the same type as the other keys of the
- table, and A of the same type as the other associates.
- .Se 5 6.3 TESTS
- .Xx bound tags
- .Xx scratch-pad copy
- .Tx
- Tests do not return a value, but succeed or fail when
- tested.
- In \*B, the testing of a test cannot alter the values of targets
- that currently exist, nor can it create new targets that survive the test,
- with the exception of the temporary survival of bound tags
- as described under QUANTIFICATIONS (section 6.3.7) and
- REFINED-TESTS (section 6.3.3).
- .br
- If a test appears to alter an existing target, it effectively modifies
- a local, ``scratch-pad''
- \fIcopy\fP of that target, and the change is invisible outside the test.
- .Sy 6
- .Pr test 6
- .Al
- tight-test
- .Al
- conjunction
- .Al
- disjunction
- .Al
- negation
- .Al
- quantification
- .Pr tight-test 6
- .Al
- \*(<:(\*(:> test \*(<:)\*(:>
- .Al
- order-test
- .Al
- proposition
- .Al
- refined-test
- .Pr right-test 4
- .Al
- tight-test
- .Al
- negation
- .Al
- quantification
- .Tx
- The various kinds of tests that are distinguished here
- serve to define the syntax
- in such a way that no parentheses are needed where the meaning is
- sufficiently clear.
- .Se 7 6.3.1 ORDER-TESTS
- .Xx order
- .Xx approximate
- .Xx exact
- .Xx equal
- .Xx number
- .Sy 7
- .Pr order-test 3
- .Al
- single-expression\0order-sign\0single-expression
- .Al
- order-test\0order-sign\0single-expression
- .Pr order-sign 7
- .Al
- \*(<:<\*(:>
- .Al
- \*(<:<=\*(:>
- .Al
- \*(<:=\*(:>
- .Al
- \*(<:<>\*(:>
- .Al
- \*(<:>=\*(:>
- .Al
- \*(<:>\*(:>
- .Ps
- (The order-sign \*(<:<>\*(:> stands for ``not equals''.)
- .Ex 5
- \k1order-tests:
- \h'|\n1u'\*(<:(i', j') > (i, j)\*(:>
- \&\h'|\n1u'\*(<:'0' <= d <= '9'\*(:>
- \h'|\n1u'\*(<:fa <= f(x) >= fb\*(:>
- .Xe
- The single-expressions are evaluated one by one, from left to right,
- and each adjacent pair is compared.
- As soon as a comparison does not comply with the given order-sign,
- the whole order-test fails and no further single-expressions are evaluated.
- The order-test succeeds if all comparisons comply with the
- specified order-signs.
- .br
- Note carefully that an approximate number is \fInever\fP equal to an exact
- number, so, for instance, if you want to compare an approximate number \*(<:a\*(:>
- for equality with an exact number \*(<:e\*(:>, you should write
- .Di 1
- \*(<:IF a = ~e:\*(:>\ ...
- .Ed
- .br
- This also allows you to test if a number is exact or not:
- .Di 3
- \*(<:SELECT:
- x = ~x: WRITE 'Approximate'
- ELSE: WRITE 'Exact'\*(:>
- .Ed
- .Se 2 6.3.2 PROPOSITIONS
- .Xx proposition
- .Xx user-defined predicate
- .Xx scratch-pad copy
- .Xx test-unit
- .Xx report-command
- .Xx succeed-command
- .Xx fail-command
- .Xx text, list or table
- .Sy 2
- .Pr zeroadic-proposition 2
- .Sl
- zeroadic-predicate
- .Pr monadic-proposition 2
- .Sl
- monadic-predicate\0actual-operand
- .Pr dyadic-proposition 2
- .Al
- actual-operand\0dyadic-predicate\0actual-operand
- .Pr zeroadic-predicate 2
- .Sl
- tag
- .Pr monadic-predicate 2
- .Sl
- tag
- .Pr dyadic-predicate 2
- .Sl
- tag
- .Us 7 Propositions with user-defined predicates
- A proposition whose predicate is defined by a test-unit, is
- tested in the following steps:
- .in \w'2.\ 'u
- .ti 0
- 1.\ A copy is made of the current environment (the value of
- all targets), and all computations during the testing of
- the proposition will take place in this ``scratch-pad copy''.
- .ti 0
- 2.\ Any local tags in the test-unit that might clash with tags currently
- in use are systematically replaced by other tags that do not cause conflict.
- .ti 0
- 3.\ Each actual-operand is evaluated and put in the
- corresponding formal-operand, used as a (new)
- target.
- .ti 0
- 4.\ The command-suite of the unit, thus modified, is executed.
- .in 0
- The testing of the proposition is complete when the execution
- of this command-suite terminates because of the execution
- of a report-, succeed- or fail-command;
- the proposition succeeds or fails accordingly.
- .Us 7 Propositions with predefined predicates
- .Qr
- \*(<:e in t\*(:>
- .Qe
- accepts texts, lists and tables for the right operand.
- It succeeds if \*(<:e#t > 0\*(:> succeeds,
- in other words, if the value \*(<:e\*(:> occurs in \*(<:t\*(:>.
- .Qr
- \*(<:e not'in t\*(:>
- .Qe
- is the same as \*(<:(NOT e in t)\*(:>.
- .Se 2 6.3.3 REFINED-TESTS
- .Xx scratch-pad copy
- .Xx report-command
- .Xx succeed-command
- .Xx fail-command
- .Xx bound tags
- .Sy 2
- .Pr refined-test 2
- .Sl
- tag
- .Sx 3 \k1refined-test:
- \*(<:special'case\*(:>
- .Xe
- .Tx
- A refined-test is
- tested in the following steps:
- .in \w'2.\ 'u
- .ti 0
- 1.\ A copy is made of the current environment (the value of all targets),
- and all computations during the testing of
- the test will take place in this ``scratch-pad copy''.
- .ti 0
- 2.\ The command-suite of the corresponding
- test-refinement is executed.
- .in 0
- The testing of the refined-test is complete when the execution
- of this command-suite terminates because of the execution
- of a report-, succeed- or fail-command, and the refined-test
- succeeds or fails accordingly.
- .ne 3
- .br
- Any bound tags set by a for-command or
- a quantification (see 6.3.7) at that time will temporarily survive
- for those parts that are reachable only by virtue of the outcome of the test.
- This is so that you can turn any test into a refined-test with the same effect.
- .br
- For example, in
- .Di 3
- \*(<: IF divisible AND n > d**2: WRITE d
- \*(:>...\*(<:
- divisible: REPORT SOME d IN {2..n-1} HAS n mod d = 0\*(:>,
- .Ed
- the bound tag \*(<:d\*(:> is set to a divisor of \*(<:n\*(:> if the
- refined-test succeeds, and since the part \*(<:n > d**2\*(:>
- is only reached after success, \*(<:d\*(:> may be used there.
- The same is true for the write-command using \*(<:d\*(:>.
- The line after (indicated with three dots), however, can be
- reached if the divisibility test fails.
- So there \*(<:d\*(:> has ceased to exist.
- .Sa
- test-refinements (4.4).
- .Se 2 6.3.4 CONJUNCTIONS
- .Sy 2
- .Pr conjunction 3
- .Al
- tight-test \*(<:AND\*(:> right-test
- .Al
- tight-test \*(<:AND\*(:> conjunction
- .Ex 4
- \k1conjunctions:
- \h'|\n1u'\*(<:a > 0 AND b > 0\*(:>
- \h'|\n1u'\*(<:i in keys t AND t[i] in keys u AND u[t[i]] <> 'dummy'\*(:>
- .Xe
- .Tx
- The tests of the conjunction, separated by \*(<:AND\*(:>, are tested
- one by one, from left to right.
- As soon as one of these tests fails,
- the whole conjunction fails and no further parts
- are tested.
- The conjunction succeeds if all its tests succeed.
- .Se 2 6.3.5 DISJUNCTIONS
- .Sy 2
- .Pr disjunction 3
- .Al
- tight-test \*(<:OR\*(:> right-test
- .Al
- tight-test \*(<:OR\*(:> disjunction
- .Ex 4
- \k1disjunctions:
- \h'|\n1u'\*(<:a <= 0 OR b <= 0\*(:>
- \h'|\n1u'\*(<:n = 0 OR s[1] = s[n] OR t[1] = t[n]\*(:>
- .Xe
- .Tx
- The tests of the disjunction, separated by \*(<:OR\*(:>, are tested
- one by one, from left to right.
- As soon as one of these tests succeeds,
- the whole disjunction succeeds and no further parts
- are tested.
- The disjunction fails if all its tests fail.
- .Se 2 6.3.6 NEGATIONS
- .Sy 2
- .Pr negation 2
- .Sl
- \*(<:NOT\*(:> right-test
- .Sx 3 \k1negation:
- \*(<:NOT a subset b\*(:>
- .Xe
- .Tx
- A negation succeeds if its right-test fails, and fails if
- that test succeeds.
- .Se 3 6.3.7 QUANTIFICATIONS
- .Xx bound tags
- .Xx text, list or table
- .Xx character
- .Xx list entry
- .Xx associate
- .Sy 3
- .Pr quantification 2
- .Sl
- quantifier\0ranger \*(<:HAS\*(:> right-test
- .Pr quantifier 4
- .Al
- \*(<:SOME\*(:>
- .Al
- \*(<:EACH\*(:>
- .Al
- \*(<:NO\*(:>
- .Pr ranger 3
- .Al
- in-ranger
- .Al
- parsing-ranger
- .Pr parsing-ranger 3
- .Sl
- multiple-identifier \*(<:PARSING\*(:> expression
- .Ps
- Note that the identifier of a parsing-ranger must be a multiple-identifier
- (like \*(<:p, q, r\*(:>):
- it may not be a single-identifier (like \*(<:pqr\*(:>).
- Moreover, each of the single-identifiers (like \*(<:p\*(:>) must be
- plain tags.
- The reason is that this determines the number of parts
- which the value of the expression must be split into (see below).
- .Bl 1
- (For in-rangers, see for-commands, section 5.2.4.)
- .Ex 5
- \k1quantifications:
- \h'|\n1u'\*(<:SOME p, q, r PARSING line HAS q in {'. '; '? '; '! '}\*(:>
- \h'|\n1u'\*(<:EACH i, j IN keys t HAS t[i, j] = t[j, i]\*(:>
- \h'|\n1u'\*(<:NO d IN {2..n-1} HAS n mod d = 0\*(:>
- .Xe
- .Tx
- The tags of the identifier of a quantifier may not be used as targets
- or target-contents
- outside such a quantifier.
- They are ``bound tags'', and lose their meaning outside the
- quantifier, except as described below.
- .Bl 2
- The meaning of quantifications will first be described for
- the case of \*(<:SOME\*(:>\ ...\ \*(<:IN\*(:>\ ...
- .br
- The value of the expression must be a text, list or table.
- The items (characters, list entries or associates) of that value are
- assigned one by one to the identifier, and the right-test is
- tested each time.
- The quantification succeeds as soon as
- the right-test succeeds once.
- It fails only if the text, list or table is exhausted and the
- right-test has failed each time.
- .br
- If the quantification succeeds,
- the bound tags set at that moment
- will temporarily survive and may be used
- in those parts that are reachable only by virtue of the
- outcome of the test.
- .br
- For example, in
- .Di 3
- \*(<: IF (SOME d IN {2..n-1} HAS n mod d = 0) AND n > d**2: WRITE d
- \*(:>\ ...
- .Ed
- the bound tag \*(<:d\*(:> is set to a divisor of \*(<:n\*(:> if the
- quantification succeeds, and since the part \*(<:n > d**2\*(:>
- is only reached after success, \*(<:d\*(:> may be used there.
- The same is true for the write-command using \*(<:d\*(:>.
- So, if \*(<:n\*(:> has the value \*(<:77\*(:>, \*(<:7\*(:> will be written, since
- the test \*(<:n mod d = 0\*(:> succeeds the first time when
- \*(<:d\*(:> is set to \*(<:7\*(:> (and \*(<:77 > 7**2\*(:>).
- The line after (indicated with three dots), however, can be
- reached if the divisibility test fails.
- So there \*(<:d\*(:> has ceased to exist and may not be used.
- .sp
- The meaning of a quantification \*(<:SOME id IN tlt HAS prop\*(:>
- can also be described as the meaning of the refined-test
- \*(<:test'if'some\*(:>, given
- a test-refinement
- .Di 4
- \*(<:test'if'some:
- FOR id IN tlt:
- IF prop: SUCCEED
- FAIL\*(:>
- .Ed
- .Bl 3
- The meaning of \*(<:EACH id IN tlt HAS prop\*(:>
- is the same as that of \*(<:NOT SOME id IN tlt HAS NOT prop\*(:>.
- In other words, an \*(<:EACH\*(:> quantification succeeds only if its
- right-test succeeds each time.
- .br
- The meaning of \*(<:NO id IN tlt HAS prop\*(:>
- is the same as that of \*(<:NOT SOME id IN tlt HAS prop\*(:>.
- In other words, a \*(<:NO\*(:> quantification succeeds only if its
- right-test fails each time.
- .br
- The rules for temporary survival are the same as for \*(<:SOME\*(:>.
- So an \*(<:EACH\*(:> or \*(<:NO\*(:> quantification will only have set its
- bound tags on failure.
- Thus, in the following, the bound tag \*(<:d\*(:> survives into the \*(<:ELSE\*(:>:
- .Di 4
- \*(<:SELECT:
- NO d IN {2..n-1} HAS n mod d = 0:
- WRITE 'prime'
- ELSE: WRITE 'divisible by `d`'\*(:>
- .Ed
- .Bl 3
- If \*(<:PARSING\*(:> is specified,
- all \fIparsings\fP of the value of the given expression are
- tried, instead of its items.
- The value of the expression must be a text.
- A ``parsing'' of a text is a way of splitting it in parts.
- The text is split in all possible ways in as many parts as
- there are tags in the multiple-identifier, and each split
- is put in that identifier, whereupon the right-test is tested.
- For example,
- .Di 1
- \*(<:SOME p, q, r PARSING 'abracadabra' HAS (p = r AND #p > 3)\*(:>
- .Ed
- will succeed with \*(<:p\*(:> and \*(<:r\*(:> set to \*(<:'abra'\*(:> and \*(<:q\*(:> set to \*(<:'cad'\*(:>.
- If the test \*(<:#p > 3\*(:> is omitted, the quantification will
- succeed with the uninteresting result that \*(<:p\*(:> and \*(<:r\*(:> are set
- to \*(<:''\*(:> and \*(<:q\*(:> to \*(<:'abracadabra'\*(:>.
- .br
- To give another example,
- .Di 3
- \*(<: PUT 'a man, a plan, a canal: panama!' IN palindrome
- WHILE SOME hd, x, tl PARSING palindrome HAS x'non'letter:
- PUT hd^tl IN palindrome
- WRITE palindrome /
- x'non'letter: REPORT #x = 1 AND x not'in {'a'..'z'}\*(:>
- .Ed
- will successively find and remove all non-letters from the
- text in \*(<:palindrome\*(:> finally leaving the text \*(<:'amanaplanacanalpanama'\*(:>.
- (This is not a recommended way, because it will be very slow.
- There are equally simple and much faster ways to achieve the same effect.
- The example is only chosen to illustrate the possibilities of \*(<:PARSING\*(:>.)
- Note that the test \*(<:#x = 1\*(:> here is essential.
- If it is omitted, the program will go
- into an endless loop ``removing'' empty texts \*(<:x\*(:> from \*(<:palindrome\*(:>.
- .br
- The meaning of \*(<:SOME p, q,\*(:>\ ...\ \*(<:PARSING whole HAS prop\*(:>
- may more precisely be described as follows.
- Let \*(<:parsings\*(:> stand for a list, containing
- \fIall\fP compounds with the same number of fields as the
- multiple-identifier \*(<:p, q,\*(:>\ ..., such that those fields
- (which are texts) joined together give the text \*(<:whole\*(:>.
- For example, in
- .Di 1
- \*(<:SOME p, q, r PARSING 'abracadabra' HAS (p = r AND #p > 3)\*(:>
- .Ed
- the list \*(<:parsings\*(:> will begin with
- .Di 1
- \*(<:{('', '', 'abracadabra'); ('', 'a', 'bracadabra');\*(:>\ ...\ ,
- .Ed
- contain somewhere in the middle
- .Di 1
- \&...\ \*(<:; ('abra', 'cad', 'abra');\*(:>\ ...\ ,
- .Ed
- and end with
- .Di 1
- \&...\ \*(<:; ('abracadabr', 'a', ''); ('abracadabra', '', '')}\*(:>.
- .Ed
- The effect of the quantification is then the same as that
- of
- .Di 1
- \*(<:SOME p, q,\*(:>\ ...\ \*(<:IN parsings HAS prop\*(:>.
- .Ed
- The meaning of \*(<:EACH\*(:> or \*(<:NO\*(:> is accordingly defined.
- .Sa
- for-commands (5.2.4).
- .ps 10
- .vs 12
- .de PH\"Page Header
- .ie \\n+(cl<3 \{\
- .po +\\n(TWu/3u
- .rt
- .ns \}
- .el \{\
- .po \\n(POu
- .nr f1 \\n(.f\" current font
- .ft
- .nr f2 \\n(.f\" previous font
- .ft R
- .nr sp \\n(.s\"current point size
- .ps \\n(ms-1
- 'bp
- .CM \" Cut Mark
- 'ie o 'tl ''\\*(TL'\\*(Sn'
- 'el 'tl '\\*(Sn'\\*(TL''
- .ft \\n(f2\" restore previous font
- .ft \\n(f1\" restore current font
- .ps \\n(sp\"restore point size
- 'sp 2
- .mk
- 'ns
- 'EH\"Extra Header
- 'nr cl 0 1 \}
- 'na
- ..
- .ch PH
- .wh -(\n(HFu-1v) PH
- .de Fo\" Page footer
- .nr f1 \\n(.f\" current font
- .ft
- .nr f2 \\n(.f\" previous font
- .ft R
- .nr sp \\n(.s\"current point size
- .ps \\n(ms-1
- .po \\n(POu
- .if \\n%>2 .tl ''%''
- .po
- .ft \\n(f2\" restore previous font
- .ft \\n(f1\" restore current font
- .ps \\n(sp\"restore point size
- ..
- .de XX
- .br
- .ti 0
- ..
- .ds Sn Index
- .nr cl 4 1
- .ll \n(TWu/3u-2n
- .na
- .bp
- .Us 3 INDEX
- .mk
- .in 2n
- .XX
- actual-operand 6.1.6
- .XX
- actual-parameter 5.1.16
- .XX
- alternative-sequence 5.2.2
- .XX
- alternative-suite 5.2.2
- .XX
- ambiguity 6.1.5, 6.1.6
- .XX
- approximate 6.3.1
- .XX
- approximate-constant 6.1.1
- .XX
- approximate number 1
- .XX
- associate 1, 5.1.6, 5.2.4, 6.1.4, 6.1.5, 6.1.6, 6.2.3, 6.3.7
- .XX
- basic-expression 6.1
- .XX
- basic-target 6.2
- .XX
- bound tags 5.1.13, 5.1.14, 5.1.15, 5.2.4, 6.3, 6.3.3, 6.3.7
- .XX
- brackets 6.1.6
- .XX
- character 1, 5.1.6, 5.2.4, 6.1.5, 6.1.6, 6.3.7
- .XX
- check-command 5.1.1
- .XX
- choose-command 5.1.6
- .XX
- command 5
- .XX
- command-refinement 4.4, 5.1.11, 5.1.17
- .XX
- command-sequence 4.5
- .XX
- command-suite 4.5
- .XX
- comment 3
- .XX
- compound 1, 6.1, 6.2
- .XX
- conjunction 6.3.4
- .XX
- control-command 5.2
- .XX
- conversion 6.1.5
- .XX
- convert to a text 5.1.2, 6.1.5, 6.1.6
- .XX
- decrease-indentation 3
- .XX
- delete-command 5.1.10
- .XX
- denominator 6.1.6
- .XX
- digit 6.1.1
- .XX
- disjunction 6.3.5
- .XX
- display 6.1.5
- .XX
- draw-command 5.1.5
- .XX
- dyadic 4.2, 4.3
- .XX
- dyadic-formula 6.1.6
- .XX
- dyadic-function 6.1.6
- .XX
- dyadic-predicate 6.3.2
- .XX
- dyadic-proposition 6.3.2
- .XX
- else-alternative 5.2.2
- .XX
- empty 2
- .XX
- empty list 6.1.5
- .XX
- empty table 6.1.5
- .XX
- entry 1
- .XX
- equal 6.3.1
- .XX
- exact 6.3.1
- .XX
- exact-constant 6.1.1
- .XX
- exact number 1
- .XX
- exponent-part 6.1.1
- .XX
- expression 6.1
- .XX
- expression-refinement 4.4, 4.5, 5.1.12, 6.1.7
- .XX
- fail-command 4.5, 5.1.15, 6.3.2, 6.3.3
- .XX
- field 1
- .XX
- for-command 5.2.4
- .XX
- formal-dyadic-formula 4.2
- .XX
- formal-dyadic-proposition 4.3
- .XX
- formal-formula 4.2
- .XX
- formal-monadic-formula 4.2
- .XX
- formal-monadic-proposition 4.3
- .XX
- formal-operand 4.2
- .XX
- formal-parameter 4.1
- .XX
- formal-proposition 4.3
- .XX
- formal-tail 4.1
- .XX
- formal-trailer 4.1
- .XX
- formal-user-defined-command 4.1
- .XX
- formal-zeroadic-formula 4.2
- .XX
- formal-zeroadic-proposition 4.3
- .XX
- formula 4.2, 4.3, 6.1.6
- .XX
- fractional-part 6.1.1
- .XX
- function 4.2, 4.3, 6.1.6
- .XX
- further-comment 3
- .XX
- global 4.5, 5
- .XX
- how-to-unit 4.1, 5.1.11, 5.1.16
- .XX
- identifier 6.2.1
- .XX
- if-command 5.2.1
- .XX
- immediate command 5, 5.1.11
- .XX
- in-ranger 5.2.4
- .XX
- increase-indentation 3
- .XX
- indentation 3
- .XX
- insert-command 5.1.9
- .XX
- integer 6.1.3, 6.1.5, 6.1.6
- .XX
- integral-part 6.1.1
- .XX
- interrupt key 5, 5.1.2
- .XX
- key 1, 6.1.4, 6.1.5, 6.1.6, 6.2.3
- .XX
- keyword 3, 4.1, 4.4, 5.1.16, 5.1.17
- .XX
- list 1
- .XX
- list-body 6.1.5
- .XX
- list-display 6.1.5
- .XX
- list entry 1, 5.1.6, 5.1.8, 5.1.9, 5.2.4, 6.1.6, 6.3.7
- .XX
- list-filler 6.1.5
- .XX
- list-filler-series 6.1.5
- .XX
- local 4.5, 6.1.6, 6.2.1
- .XX
- location 5.1.4, 5.1.10, 6.2.1, 6.2.3
- .XX
- monadic 4.2, 4.3
- .XX
- monadic-formula 6.1.6
- .XX
- monadic-function 6.1.6
- .XX
- monadic-predicate 6.3.2
- .XX
- monadic-proposition 6.3.2
- .XX
- multiple-expression 6.1
- .XX
- multiple-identifier 6.2.1
- .XX
- multiple-target 6.2
- .XX
- negation 6.3.6
- .XX
- new-line 3
- .XX
- new-line-proper 3
- .XX
- new-liners 5.1.2
- .XX
- number 1, 5.1.5, 6.1.6, 6.3.1
- .XX
- numerator 6.1.6
- .XX
- numeric-constant 6.1.1
- .XX
- optional-ANYTHING 2
- .XX
- order 1, 6.3.1
- .XX
- order-sign 6.3.1
- .XX
- order-test 6.3.1
- .XX
- overloading of functions and predicates 4.2, 4.3
- .XX
- parentheses 6.1.6
- .XX
- parsing-ranger 6.3.7
- .XX
- permanent environment 4.5, 5.1.2, 5.1.11
- .XX
- plusminus 6.1.1
- .XX
- predefined functions 6.1.6
- .XX
- predefined predicates 6.3.2
- .XX
- predicate 4.2, 4.3
- .XX
- priority 6.1.6
- .XX
- proposition 4.3, 6.3.2
- .XX
- put-command 5.1.4
- .XX
- quantification 6.3.7
- .XX
- quantifier 6.3.7
- .XX
- quit-command 5.1.11, 5.1.16, 5.1.17
- .XX
- quote 6.1.5
- .XX
- random 5.1.5, 5.1.6, 5.1.7
- .XX
- ranger 6.3.7
- .XX
- read-command 5.1.3
- .XX
- refined-command 5.1.17
- .XX
- refined-expression 5.1.12, 6.1.7
- .XX
- refined-test 5.1.13, 5.1.14, 5.1.15, 6.3.3
- .XX
- refinement 4.4
- .XX
- refinement-suite 4
- .XX
- remove-command 5.1.8
- .XX
- report-command 4.5, 5.1.13, 6.3.2, 6.3.3
- .XX
- return-command 4.5, 5.1.12, 6.1.6, 6.1.7
- .XX
- right-expression 6.1
- .XX
- right-test 6.3
- .XX
- scratch-pad copy 6.1, 6.1.6, 6.1.7, 6.3, 6.3.2, 6.3.3
- .XX
- select-command 5.2.2
- .XX
- set-random-command 5.1.7
- .XX
- share-heading 4.5
- .XX
- simple-command 5.1
- .XX
- simple-expression 6.1
- .XX
- single-alternative 5.2.2
- .XX
- single-expression 6.1
- .XX
- single-identifier 6.2.1
- .XX
- single-target 6.2
- .XX
- spaces 3
- .XX
- succeed-command 4.5, 5.1.14, 6.3.2, 6.3.3
- .XX
- table 1
- .XX
- table-display 6.1.5
- .XX
- table entry 1, 5.1.10, 6.1.4, 6.2.3
- .XX
- table-filler 6.1.5
- .XX
- table-filler-series 6.1.5
- .XX
- table-selection 6.1.4
- .XX
- table-selection-target 5.1.10, 6.2.3
- .XX
- tag 3, 6.2.1
- .XX
- target 4.5, 5.1.4, 5.2.4, 6.1.6, 6.2, 6.2.1
- .XX
- target-content 6.1.2
- .XX
- terminating-command 5.1, 5.2.3
- .XX
- test 4.3, 6.3
- .XX
- test-refinement 4.4, 4.5, 5.1.13, 5.1.14, 5.1.15
- .XX
- test-unit 4.3, 4.5, 5.1.13, 5.1.14, 5.1.15, 6.3.2
- .XX
- text 1, 6.1.6
- .XX
- text, list and table 5.1.6, 5.2.4, 6.1.6, 6.3.2, 6.3.7
- .XX
- text-display 6.1.5
- .XX
- tight-expression 6.1
- .XX
- tight-test 6.3
- .XX
- trailer 5.1.16
- .XX
- trimmed-text 6.1.3
- .XX
- trimmed-text-target 6.2.2
- .XX
- type 5.1.4, 6.2.3
- .XX
- unit 4
- .XX
- user-defined-command 4.1, 5.1.16
- .XX
- user-defined-function 4.2, 5.1.12, 6.1.6
- .XX
- user-defined-predicate 4.3, 5.1.13, 5.1.14, 5.1.15, 6.3.2
- .XX
- while-command 5.2.3
- .XX
- work-space 4, 4.5
- .XX
- write-command 5.1.2
- .XX
- yield-unit 4.2, 4.5, 5.1.12, 6.1.6
- .XX
- zeroadic 4.2, 4.3
- .XX
- zeroadic-formula 6.1.6
- .XX
- zeroadic-function 6.1.6
- .XX
- zeroadic-predicate 6.3.2
- .XX
- zeroadic-proposition 6.3.2
- .rm PH
- .wh -0 CM
- .bp
-