Overview
--------
This workspace contains two principal functions: [eval] and [until].

[eval] gives easy access to Excel-style expression evaluation:

      )clear
clear ws

      )copy eval eval

      eval'6*9 - 8/2 + -2∧3'        ⍝ Excel-style expression evaluation.
42

[until] provides a simple input/evaluate/display loop for experimentation:

      )load eval

      until'stop'       ⍝ loop until 'stop' is input.

    2+3                 ⍝ simple expression.
5
    3-2-1               ⍝ left-to-right evaluation.
0
    7/3 + 14/3          ⍝ function (operator) precedence.
7
    round(1.234, 2)     ⍝ "macro" functions:
1.23

    floor(1.234, .01)
1.23

    sum(2.3, 4.5, 6.7)
13.5

    stop                ⍝ stop.

The  function definitions used by [eval] and [until] are "soft-coded" in a char-
acter vector "script":

      display std       ⍝ standard definitions
┌→──────────────────────────────────────────────────────────────────┐
│⍝   S t a n d a r d   E x c e l - s t y l e   d e f i n i t i o n s│
│                                                                   │
│⍝ Macros:                                                          │
│                                                                   │
│    round(num sig → mul←÷10*sig ⋄ mul×⌊0.5+num÷mul)                │
│                                                                   │
│    floor(num mul → mul×⌊num÷mul)                                  │
│                                                                   │
│    ceiling(num mul → mul×⌈num÷mul)                                │
│                                                                   │
│    sum(+/) max(⌈/) min(⌊/)     ⍝ sum(i, j, k,···)                 │
│                                                                   │
│    mod(n m → m | n)                                               │
│                                                                   │
│⍝ Arithmetic:                                                      │
│                                                                   │
│      -(-)                      ⍝ neg (unary minus)                │
│    → ∧(*)                      ⍝ pow                              │
│    ← *(×) /(÷)                 ⍝ mul div                          │
│    ← +(+) -(-)                 ⍝ add sub                          │
│                                                                   │
│    ← ,()                       ⍝ argument separator               │
└───────────────────────────────────────────────────────────────────┘

Note that definitions are kept in a "line list", which is a vector with embedded
linefeed  characters. This form uses the least amount of workspace, although the
functions that reference the source are equally happy with character matrices or
vectors of character vectors.

Macros, such as [round] and [floor] in the above script, are thinly-disguised D-
functions. For example:

    floor(num mul → mul×⌊num÷mul)

is translated into:

    floor←{num mul←⍵ ⋄ mul×⌊num÷mul}

and

    round(num sig → mul←÷10*sig ⋄ mul×⌊0.5+num÷mul)

is translated into:

    round←{num sig←⍵ ⋄ mul←÷10*sig ⋄ mul×⌊0.5+num÷mul}

It is easy to extend or restrict the functional vocabulary of [eval] and [until]
by editing and recompiling the definitions source vector.

      )ed std                   ⍝ edit standard definitions.
      load std                  ⍝ compile and install standard definitions.
      )save                     ⍝ resave ws with amended standard definitions.

In addition to the standard, there are some alternative definition vectors:

      math                      ⍝ "mathematical" definitions.
      sba                       ⍝ signed binary arithmetic.
      bta                       ⍝ balanced ternary arithmetic.
      soroban                   ⍝ Japanese abacus.
      roman                     ⍝ Roman numerals.
      tasman                    ⍝ "one, two, plenty".

To investigate one of these alternatives, simply load it.

      load math                 ⍝ mathematical definitions.     See: →#.math←

      eval'x*x∧2*4'             ⍝ simplify expression
4*x∧3

      until''                   ⍝ interactive mini-session
    exp(1)                      ⍝ exponential
2.7183
    (1/x)∆x                     ⍝ See: →Differentiation←
-1/x∧2
    x+y, x=2, y=3               ⍝ expression-local vars ("," means "where").
5
                                ⍝ etc.

In  the  scripts for non-standard number systems, dot "." is used as an explicit
digit  binding  _function_  rather  than  as a decimal point. For example, 1.2.3
might mean "one hundred and twenty three".

      load sba                  ⍝ signed binary arithmetic.     See: →#.sba←

      until''                   ⍝ experiment.
    1.1+1.1                     ⍝ 3+3 → 6
1.1.0
    1.1-1.1.1                   ⍝ 3-7 → ¯4
-1.0.0
    1.1*1.1                     ⍝ 3×3 → 9
1.0.0.1
    1.0.0.0.1/1.0.1             ⍝ ⌈17÷5 → 3
1.1
    1.0.0.0.1%1.0.1             ⍝ 17|⍨5 → 2
1.0
    1.1.1∧1.1                   ⍝ 7*3 → 343
1.0.1.0.1.0.1.1.1
                                ⍝ etc.

      load bta                  ⍝ balanced ternary arithmetic. See →bta← →#.bta←

      until''
    1.1.1+1                     ⍝ 13+1 → 14         (+/ 27 ¯9 ¯3 ¯1)
1.¯1.¯1.¯1
    1.1*1.1                     ⍝ 4×4 → 16          (+/ 27 ¯9 ¯3 1)
1.¯1.¯1.1
    -1.1.1                      ⍝ -13 → ¯13
¯1.¯1.¯1
    1.0.1∧1.0                   ⍝ 10*3 → 1000       (+/729 243 0 27 0 0 1)
1.1.0.1.0.0.1
                                ⍝ etc.

      load roman                ⍝ Roman numeral arithmetic.    →roman← →#.roman←

      until'exit'

    I.V + I.X                   ⍝ 4 + 9 → 13
X.I.I.I

    I.X × X.I                   ⍝ 9 × 11 → 99
X.C.I.X

    X.X.I.V ÷ V.I               ⍝ 24 ÷ 6 → 4
I.V

    X.X.V % V.I.I               ⍝ 25 %(mod) 7 → 4
I.V

    ⍴ 1.4.9                     ⍝ convert to Roman numerals
C.X.L.I.X

    ⍺ C.X.L.I.X                 ⍝ convert back to Arabic numbers.
1.4.9

    ⍺ ⍴ ⍺ ⍴ ⍺ ⍴ 3.2.1           ⍝ back and forth ...
3.2.1

    exit                        ⍝ etc.

Both  "eval" and "until" take an optional left argument that determines the for-
mat of the display.

      load math                 ⍝ using math definitions.

      eval'(x∧x)∆x∆x'           ⍝ standard linear format:
x∧(x-1)+x∧x*(ln(x)+1)∧2

      't'eval'(x∧x)∆x∆x'        ⍝ resulting expression in tree format.
     +
 ┌───┴───┐
 ∧       *
┌┴─┐   ┌─┴────┐
x  -   ∧      ∧
  ┌┴┐ ┌┴┐   ┌─┴┐
  x 1 x x   +  2
          ┌─┴┐
          ln 1
          └┐
           x

Operator  "script"  may  be  used to apply a function under the aegis of a given
script. In other words, the script is loaded temporarily for the duration of the
function; the operator:

- saves the currently loaded definitions;
- loads the script specified in its left operand;
- applies its right operand function to its right argument;
- restores the original definitions.

Examples:

      load std                  ⍝ starting with standard script:

                   eval'1+1'    ⍝   std 1+1
2
       math script eval'1+1'    ⍝  math 1+1
2
      roman script eval'I+I'    ⍝ roman 1+1
I.I
        bta script eval'1+1'    ⍝   bta 1+1
1.¯1
        sba script eval'1+1'    ⍝   sba 1+1
1.0
                   eval'1+1'    ⍝ standard script abides.
2

      roman script until'eximus'    ⍝ interactive roman session.

    I+I
I.I

    I.V×V.I
X.X.I.V

    eximus                          ⍝ (we quit)


      2(math script until)'→'       ⍝ math script with arboreal display.

    x+y+x+y
 *
┌┴─┐
2  +
  ┌┴┐
  y x

    x+y+x+y+x+y
       +
     ┌─┴┐
     +  y
 ┌───┴┐
 *    x
┌┴─┐
2  +
  ┌┴┐
  y x

    →

In  accordance  with Agile Programming practice, scripts contain an accumulation
of  test  cases,  which may be checked using the "test" function. Each test line
starts with a comment and contains string '->' to indicate an expected result or
'!!' to indicate an expected error. For example:

⍝   2+3 -> 5
⍝   1/0 !! bad operand

Any  differences from expected results (or errors) are displayed in the session;
this means that a correct coding produces no output. The shy result of test is a
boolean vector indicating which tests succeeded.

To test standard definitions:

      test std                      ⍝ test standard definitions.

To run all tests:

      test''                        ⍝ run all tests (no news => good news).

An optional left argument of 1 shows progress during the test:

      1 test roman                  ⍝ test roman script, showing progress.
⍝   R o m a n   N u m e r a l s     See →roman←
                 I.I.I.I -> I.V
               I.I.I.I.I -> V
             I.I.I.I.I.I -> V.I
             I+I+I+I+I+I -> V.I
                 I.V + I -> V
           V.I.I + V.I.I -> X.I.V
               I.X + I.X -> X.V.I.I.I
       X.L.I.X + X.L.I.X -> X.C.V.I.I.I
                 M+M+M+M -> nimius
                 X.X - I -> X.I.X
                        ...

See also: →#.std←
          →#.math←    →Differentiation←
          →#.sba←
          →#.bta←     →bta←
          →#.roman←   →roman←
          →#.soroban← →soroban←

Back to: →Contents