Nial as a Prototyping Language
Mike Jenkins
Emeritus Professor, School of Computing
Queen's University at Kingston
President, Nial Systems Limited
nialsys@kingston.net
based on a framework for a lecture on K by
Dennis Shasha
Courant Institute of Mathematical Sciences, NYU
Quick Tour of Nial
- # Basic arithmetic in Nial 3 * 2
- 6
- 2+3
- 5
- # Left to right precedence
- 3+5*4
- 32
- # Assignment (:= or "gets")
- A := 15*3
- 45
- B gets A / 5
- 9.
- Operations on simple lists
- # list assignment
- X := 5 3 4 -2
- 5 3 4 -2
- # element by element operations
- X + X
- 10 6 8 -4
- X * X
- 25 9 16 4
- # scalar - list operations
-
- 3*X
- 15 9 12 -6
- x / 3
- 1.66667 1. 1.33333 -0.666667
- # reducing operations
- sum X
- 10
- prod X
- -120
-
- max X
- 5
-
- # cross product
- X OUTER* X
- 25 15 20 -10
- 15 9 12 -6
- 20 12 16 -8
- -10 -6 -8 4
- # generating data
- Y := count 10
- 1 2 3 4 5 6 7 8 9 10
- Z := random 3 5
- 0.487339 0.710791 0.265316 0.162762 0.537691
- 0.974659 0.0942834 0.620331 0.910949 0.326865
- 0.623449 0.315394 0.834813 0.699439 0.478038
- # multiplication table
- Y OUTER * Y
- 1 2 3 4 5 6 7 8 9 10
- 2 4 6 8 10 12 14 16 18 20
- 3 6 9 12 15 18 21 24 27 30
- 4 8 12 16 20 24 28 32 36 40
- 5 10 15 20 25 30 35 40 45 50
- 6 12 18 24 30 36 42 48 54 60
- 7 14 21 28 35 42 49 56 63 70
- 8 16 24 32 40 48 56 64 72 80
- 9 18 27 36 45 54 63 72 81 90
- 10 20 30 40 50 60 70 80 90 100
- Tables
- A := 4 6 reshape count 24
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
-
- B := tell 4 6
- +---+---+---+---+---+---+
- |0 0|0 1|0 2|0 3|0 4|0 5|
- +---+---+---+---+---+---+
- |1 0|1 1|1 2|1 3|1 4|1 5|
- +---+---+---+---+---+---+
- |2 0|2 1|2 2|2 3|2 4|2 5|
- +---+---+---+---+---+---+
- |3 0|3 1|3 2|3 3|3 4|3 5|
- +---+---+---+---+---+---+
- Operation definition
- # average of a list of numbers
- average IS OPERATION A {
- sum A / tally A }
- average 30 40 60 80
- 52.5
Unit 1: Basic language features
- Atomic data types
- Lists
- Arrays of higher dimension
- Operations - monadic with infix use.
- Reading and writing files
- More on operations
Atomic data types
- Numeric atoms (called scalars in mathematics) # integers (32 bit integers)
- 357
- 357
- -4
- -4
- # real numbers (double floating point numbers)
- 2.5
- 2.5
- 3e5
- 300000.
- 2.5e-3
- 0.0025
- # Logical values (booleans) displayed as l and o
- True
- l
- False
- o
- # Bit strings (boolean lists)
- lollo
- lollo
-
- Symbolic atoms
- # Character, preceded by the left quote symbol:
- `x
- x
- # String (character list) characters enclosed in single quotes:
- 'Hello, world!'
- Hello, world!
- # Phrase (or symbol) characters preceded by a double quote
- "Hello
- Hello
- # or constructed from a string using operation phrase
- phrase 'Hello, world!'
- Hello, world!
- # Faults (errors or special values) symbol preceded by question mark
- ??error
- ?error
- # or constructed from a string using operation fault
- fault '?bad syntax'
- ?bad syntax
- # or result of invalid computation
- 27/0
- ?div
Lists
- Strand notation - sequence of expressions forms a list
- # list of integers
-
- 23 14 36
- 23 14 36
- # round parentheses used for grouping
- 18 -2 (25 * 4) (27 - 13)
- 18 -2 100 14
- # strand of characters is a string
- `a `b `c
- abc
- `a `b `c = 'abc'
- l
- # strand of Booleans is a bitstring
- True False True
- lol
- True False True = lol
- l
- # atomic types can be mixed
- 13 (25/4) "word
- 13 6.25 word
-
- Bracket-comma list notation [3, 42, 27] 3 42 27 [18, -3.5, `x] 18 -3.5 x # a list of atoms is called a simple list # in mathematics a simple list of numbers is called a vector
- Nested lists
- # items of lists can be lists - displayed with box diagrams
- (3 4 5) (8 9 10) (11 12 13)
- +-----+------+--------+
- |3 4 5|8 9 10|11 12 13|
- +-----+------+--------+
- # can combine list notations
- [3 4 5, 8 9 10, 11 12 13]
- +-----+------+--------+
- |3 4 5|8 9 10|11 12 13|
- +-----+------+--------+
- ["apple, "pie] ["tastes, "great]
- +---------+------------+
- |apple pie|tastes great|
- +---------+------------+
-
- # can combine lists and atoms as items
- [32,[87,"abc],True]
- +--+------+-+
- |32|87 abc|l|
- +--+------+-+
- # list items can have different lengths
- [3 4, 8 9 10, 11 12 13 14]
- +---+------+-----------+
- |3 4|8 9 10|11 12 13 14|
- +---+------+-----------+
- # can have as many levels as needed
- [3 4, 8 9 10, 11 12 13 14] 'abc'
- +------------------------+---+
- |+---+------+-----------+|abc|
- ||3 4|8 9 10|11 12 13 14|| |
- |+---+------+-----------+| |
- +------------------------+---+
-
- # binary tree of integers stored as a nested list
- [ [1, 2], [ [3, 4], 5] ]
- +---+-------+
- |1 2|+---+-+|
- | ||3 4|5||
- | |+---+-+|
- +---+-------+
- Generated lists
- # generate integers using count and tell
- tell 5
- 0 1 2 3 4
- count 20
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
- # replicate an atom using reshape
- 5 reshape "word
- word word word word word
- # generate random real numbers between 0. and 1. using random
- random 5
- 0.726391 0.448169 0.384064 0.961273 0.123186
- # generate random permutation of 10 integers using random and gradeup
- gradeup random 10
- 5 6 4 0 3 1 2 9 7 8
- gradeup random 10
- 9 6 5 0 8 3 4 7 1 2
- # operation list converts an atom to a 1-list
- list 3
- 3
- list 3 = 3
- o
- list 3 = [3]
- l
- # there is only one empty list - Null
- Null = count 0
- l
- Null = tell 0
- l
- Null = ''
- l
- # a list is a 1-dimensional array
- # a numeric list is called a vector in mathematics
Arrays of higher dimension
- Tables - 2-dimensional arrays
- # formed using reshape with a pair as the left argument
- 2 3 reshape 8 3 14 6 2 1
- 8 3 14
- 6 2 1
-
- 4 6 reshape count 24
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- # nested tables generated using count or tell
- count 3 4
- +---+---+---+---+
- |1 1|1 2|1 3|1 4|
- +---+---+---+---+
- |2 1|2 2|2 3|2 4|
- +---+---+---+---+
- |3 1|3 2|3 3|3 4|
- +---+---+---+---+
- tell 2 3
- +---+---+---+
- |0 0|0 1|0 2|
- +---+---+---+
- |1 0|1 1|1 2|
- +---+---+---+
- # construct a table by using mix on a list of lists of same length
- mix ['abcd','efgh']
- abcd
- efgh
- mix [count 5,random 5]
- 1 2 3 4 5
- 0.819432 0.193461 0.498833 0.880408 0.00925989
- # a numeric table is called a matrix in mathematics
- Higher dimensional arrays (displayed as tables)
- # formed using reshape with a longer shape vector as left argument
- 3 4 5 reshape count 60
- 1 2 3 4 5 21 22 23 24 25 41 42 43 44 45
- 6 7 8 9 10 26 27 28 29 30 46 47 48 49 50
- 11 12 13 14 15 31 32 33 34 35 51 52 53 54 55
- 16 17 18 19 20 36 37 38 39 40 56 57 58 59 60
- 2 3 4 5 reshape count 120
- 1 2 3 4 5 21 22 23 24 25 41 42 43 44 45
- 6 7 8 9 10 26 27 28 29 30 46 47 48 49 50
- 11 12 13 14 15 31 32 33 34 35 51 52 53 54 55
- 16 17 18 19 20 36 37 38 39 40 56 57 58 59 60
-
- 61 62 63 64 65 81 82 83 84 85 101 102 103 104 105
- 66 67 68 69 70 86 87 88 89 90 106 107 108 109 110
- 71 72 73 74 75 91 92 93 94 95 111 112 113 114 115
- 76 77 78 79 80 96 97 98 99 100 116 117 118 119 120
- # apply mix to a table of lists
- mix count 3 4
- 1 1 2 1 3 1
- 1 2 2 2 3 2
- 1 3 2 3 3 3
- 1 4 2 4 3 4
Operations
- Distributed atomic operations
- # operations on atom-atom, atom-list, and list-list pairs
-
- 5 + 10
- 15
- 3* count 5
- 3 6 9 12 15
- count 5 * 20 27 68 14 -3
- 20 54 204 56 -15
-
- # atomic operations descend to all levels
- 20 + count 2 3
- +-----+-----+-----+
- |21 21|21 22|21 23|
- +-----+-----+-----+
- |22 21|22 22|22 23|
- +-----+-----+-----+
- [count 2 3] * [tell 2 3]
- +-------------+
- |+---+---+---+|
- ||0 0|0 2|0 6||
- |+---+---+---+|
- ||2 0|2 2|2 6||
- |+---+---+---+|
- +-------------+
- # arithmetic, logical, comparative, and scientific operations are distributed
- lolloloo or llooolol
- llllolol
- lolloloo and llooolol
- looooloo
- exp 3 4 5
- 20.0855 54.5982 148.413
- count 10 mod 3
- 1 2 0 1 2 0 1 2 0 1
- count 10 quotient 3
- 0 0 1 1 1 2 2 2 3 3
- # sizes must be equal, unless of length 1
- count 5 + 2 3
- ?conform
- [3 4 5, 6 7 8] + [7 8 9, 10 11 12 13]
- +--------+--------+
- |10 12 14|?conform|
- +--------+--------+
- [3 4 5, 6 7 8] + [7 8 9, 10]
- +--------+--------+
- |10 12 14|16 17 18|
- +--------+--------+
- # accumulative operations
- sum count 20
- 210
-
- prod count 6
- 720
- max 3 5 -7 18 -4
- 18
- min 3 5 -7 18 -4
- -7
- or llolool
- l
- and llolool
- o
- Structural operations
- You have already learned of the structural operations reshape and mix.
- Here are some others.
- # rows - converts a table into a list of its rows
- A := 4 6 reshape count 24
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- rows A
- +-----------+--------------+-----------------+-----------------+
- |1 2 3 4 5 6|7 8 9 10 11 12|13 14 15 16 17 18|19 20 21 22 23 24|
- +-----------+--------------+-----------------+-----------------+
- # cols - converts a table into a list of its columns
- cols A
- +---------+---------+---------+----------+----------+----------+
- |1 7 13 19|2 8 14 20|3 9 15 21|4 10 16 22|5 11 17 23|6 12 18 24|
- +---------+---------+---------+----------+----------+----------+
- # flip - interchanges top two levels of an array
- flip rows A
- +---------+---------+---------+----------+----------+----------+
- |1 7 13 19|2 8 14 20|3 9 15 21|4 10 16 22|5 11 17 23|6 12 18 24|
- +---------+---------+---------+----------+----------+----------+
- cols A = flip rows A
- l
- # transpose - transposes the rows and columns of a table
- transpose A
- 1 7 13 19
- 2 8 14 20
- 3 9 15 21
- 4 10 16 22
- 5 11 17 23
- 6 12 18 24
- # mix merges the top two levels of an array
- mix rows A
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- mix cols A = transpose A
- l
-
- # reverse - reverses the items in an array
- reverse count 10
- 10 9 8 7 6 5 4 3 2 1
-
- reverse A
- 24 23 22 21 20 19
- 18 17 16 15 14 13
- 12 11 10 9 8 7
- 6 5 4 3 2 1
- # rotate - rotates the items of an array
- 3 rotate count 10
- 4 5 6 7 8 9 10 1 2 3
- -4 rotate count 10
- 7 8 9 10 1 2 3 4 5 6
- # take - selects items from an array from the ends
- 4 take tell 7
- 0 1 2 3
- -3 take count 7
- 5 6 7
- 3 4 take A
- 1 2 3 4
- 7 8 9 10
- 13 14 15 16
- -3 -3 take A
- 10 11 12
- 16 17 18
- 22 23 24
-
- # drop - selects items of an array after dropping some from the ends
- 3 drop tell 15
- 3 4 5 6 7 8 9 10 11 12 13 14
- 2 4 drop A
- 17 18
- 23 24
- -2 1 drop A
- 2 3 4 5 6
- 8 9 10 11 12
- # link - joins lists
- count 5 link tell 10
- 1 2 3 4 5 0 1 2 3 4 5 6 7 8 9
- # list - unwinds an array into its items
- list A
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
- list count 2 3
- +---+---+---+---+---+---+
- |1 1|1 2|1 3|2 1|2 2|2 3|
- +---+---+---+---+---+---+
- Measuring and testing operations
- Nial has operations to measure the dimensionality, extents of dimensions and the
- number of items in an array. These are: valence, shape and tally.
- A := 4 6 reshape count 24
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- valence A
- 2
- shape A
- 4 6
- tally A
- 24
- There are a number of operations that test array properties.
- # testing if an array is atomic
- atomic 54
- l
- atomic 4 5 6
- o
- # testing if an array is empty
- empty Null
- l
- empty count 5
- o
- Subarray selection operations
- # selecting the unique items of an array
- cull 23 14 2 5 3 2 8 14 -2 -3 1 -2
- 23 14 2 5 3 8 -2 -3 1
- # selecting by bitstring pattern
- lollol sublist count 6
- 1 3 4 6
- A mod 3 match 0 sublist A
- 3 6 9 12 15 18 21 24
- Defining operations, definition files
- # defining an operation with one parameter
- average IS OPERATION A { sum A / tally A }
-
- average 4 17 23 18 45
- 21.4
- # defining an operation with two parameter
- upto IS OP M N { M + tell (N - M + 1) }
- 3 upto 7
- 3 4 5 6 7
- # create a text file named examples.ndf with content:
- # examples
- # defining an operation with one parameter
- average IS OPERATION A { sum A / tally A }
-
- # defining an operation with two parameter
- upto IS OP M N { M + tell (N - M + 1) }
- # multiple parameters, multiple lines
- foo is OP A B C D E {
- X gets A + B + C;
- D gets D * E;
- X/D
- }
- # loaddefs - loads a script file, adds definitions to the workspace
- loaddefs "examples l
- # examples
- # defining an operation with one parameter
- average IS OPERATION A { sum A / tally A }
-
- # defining an operation with two parameter
- upto IS OP M N { M + tell (N - M + 1) }
- # multiple parameters, multiple lines
- foo is OP A B C D E {
- X gets A + B + C;
- D gets D * E;
- X/D
- }
- # using: loaddefs "examples
- # loads the script silently
- # use foo
- foo 3 4 5 6 7
- 0.285714
- foo reverse 3 4 5 6 7
- 1.5
- # see - displays a defined operation in canonical form
- see "average
- average IS OPERATION A {
- + A / tally A }
- see "foo
- foo IS OPERATION A B C D E {
- X := A + B + C ;
- D := D * E ;
- X / D }
- Syntax rules for operations
- # all operations are monadic
- + 3 4
- 7
- reshape 6 8
- 8 8 8 8 8 8
- take -3 (count 5)
- 3 4 5
- # all operations can be used prefix or infix - by rule A f B = f A B
- 3 sum 4
- 7
- + 3 4 5
- 12
- # some operations require a pair as argument
- reshape 4 5 6
- ?argument of reshape must be a pair
- # infix uses are executed left-to-right
- 3*4+5
- 17
- 3+5*4
- 32
- 10 reshape 8 / 4
- 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
- 3 + 2 reshape 10 - 1
- 9 9 9 9 9
- # sequence of prefix uses obey composition rule (f g) A = f g A = f (g A)
- sum count reverse 2 3
- 12 9
- sum count 2 3
- 9 12
- # mixed infix prefix use obeys rule A f g B = A f (g B) = f A (g B)
- 2 tell sum 2 3
- +---+---+---+---+---+
- |0 0|0 1|0 2|0 3|0 4|
- +---+---+---+---+---+
- |1 0|1 1|1 2|1 3|1 4|
- +---+---+---+---+---+
- # special rule for defined operations with two or more parameters - argument must be
- # a list that matches in length
- foo 3 4 5
- ?op_parameter
- 23 foo 4 5 6
- ?op_parameter
- upto 6
- ?op_parameter
Reading and writing files
- write strings to a file
- The operation putfile writes a list of strings to a file in ascii form.
- It places a newline indicator (CR-LF in Windows, newline in Linux) after
- each string that is written.
- "foobar putfile 'first line' 'second line'
- The list can be in strand or bracket-comma notation or the value of a variable.
- read strings from a file
- The operation getfile reads ascii characters from a file separating them into strings.
- It removes the newline indicators between strings and returns a list of strings.
-
- getfile "foobar
- +----------+-----------+
- |first line|second line|
- +----------+-----------+
- append string to a file
- The operation appendfile appends one or more strings to an existing file.
- "foobar appendfile 'third line' 'last line'
- getfile "foobar
- +----------+-----------+----------+---------+
- |first line|second line|third line|last line|
- +----------+-----------+----------+---------+
-
More on operations
- Syntax The form of an operation definintion is
- opname IS OP parameters { expr-sequence }
- which defines the operation opname.
- Consider foo again
- see "foo
- foo IS OPERATION A B C D E {
- X := A + B + C ;
- D := D * E ;
- X / D }
- It has 5 formal parameters that are passed by value and a local variable X.
- The body of the definnition consists of 3 expressions.
- The first two assign expressions assign values to X and D.
- The third expression computes X / D as the result of the operation.
- When we use foo in the application
- foo reverse 3 4 5 6 7
- 1.5
- the argument to foo is the result of
- reverse 3 4 5 6 7
- 7 6 5 4 3
- The items of this list are bound to the parameters A, B, C, D and E respectively.
- On execution,
- X is assigned 7+6+5 = 18
- D is assigned 4*3 = 12
- and the result 18/12 = 1.5
- is returned.
- Modifying operations (using transformers) Nial provides second order functions called transformers that modify operations
- to achieve specific effects.
- For example, EACH modifies its argument function f so that
- (EACH f) A applies f to the items of A.
- A transformer is always used prefix and it is applied before the operation. Thus
- EACH count 3 5 7
- +-----+---------+-------------+
- |1 2 3|1 2 3 4 5|1 2 3 4 5 6 7|
- +-----+---------+-------------+
- is the same as
- (EACH f) count 3 5 7
- +-----+---------+-------------+
- |1 2 3|1 2 3 4 5|1 2 3 4 5 6 7|
- +-----+---------+-------------+
- A
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- (EACH sum) rows A
- 21 57 93 129
- can be written
- EACH sum rows A
- 21 57 93 129
- Another example of a transformer is OUTER, where
- A OUTER f B
- applies f to each of the pairs formed from A and B.
- 4 5 OUTER * 2 7 9
- 8 28 36
- 10 35 45
- Recursive operations Recursion works as expected in Nial
- fact IS OP N { IF N = 0 THEN 1 ELSE N * fact (N - 1) ENDIF }
- fact 6
- 720
- Atlas of operations Nial uses bracket-comma notation to represent a set of operations.
- It forms an operation that applies each of the component operations to the
- argument of the atlas to get a list result.
- [3+, fact, 10*] 6
- 9 720 60
Unit 2: More advanced features
Like C, Nial has programming structures for conditional execution.
NIal also has loops, though programs usually run faster and are shorter if you avoid using them.
We discuss these features and the EACH transformers that often render loops unnecessary.
Topics
- Conditionals and loops
- EACH and related transformers
- Using array addresses
Conditionals and loops
- IF statements and expressions
- X := 5; Y := 7;
- # conditional using statements
- IF X < Y THEN
- Sml := X; Lrg := Y;
- ELSE
- Sml := Y; Lrg := X;
- ENDIF;
- # conditional using expressions
- Sml := IF X < Y THEN X ELSE Y ENDIF;
- Lrg := IF X < Y THEN Y ELSE X ENDIF;
- # using multiple assignments to do the test just once
- X Y := 5 7;
- Sml Lrg := IF X < Y THEN X Y ELSE Y X ENDIF;
- Aside:
- All expressions in Nial return a value, including assignments.
- The value of an expression ending with ; is the fault ?noexpr
- By convention this fault value is not displayed at the top level execution.
- To see the fault enclose the result in a one-list.
- [ (X := 5;) ]
- ?noexpr
- Loops
- # FOR loop
- Use a FOR loop when you know the number of steps (definite iteration)
- Total := 0;
- FOR I WITH 10 20 30 40 DO
- Total := Total + (Pi * I);
- ENDFOR;
- Total
- 314.159
- # Can often achieve the effect of a FOR loop using an expression with an EACH transformer
- sum EACH (Pi*) 10 20 30 40
- 314.159
- # implicit loops are generally faster in Q'Nial
- # WHILE loop
- Use a WHILE loop when you don't know how many steps it will take (indefinite iteration)
- # computer the series 1 + 1/(2*2) + 1/(3*3) + ... + (1/(N*N) to 5 decimal places
- Term := 1;
- I := 1;
- Total := 0;
- WHILE Term > 1e-5 DO
- TOTAL := Total + Term;
- I := I + 1;
- Term := 1 / (I * I);
- ENDWHILE;
- Total I
- 1.64393 317
EACH and related transformers
- EACH
- EACH modifies its operation argument to apply it to all the items
- of the argument array. The result has the same shape as the argument
- RULE: shape (EACH f A) = shape A
- A gets 4 6 reshape count 24
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- EACH (2+) A
- 3 4 5 6 7 8
- 9 10 11 12 13 14
- 15 16 17 18 19 20
- 21 22 23 24 25 26
- Two EACH applications can be combined.
- RULE: (EACH f) (EACH g) A = EACH(f g) A
- EACH exp EACH (2+) A
- 20.0855 54.5982 148.413 403.429 1096.63 2980.96
- 8103.08 22026.5 59874.1 162755. 442413. 1.2026e+06
- 3.26902e+06 8.88611e+06 2.4155e+07 6.566e+07 1.78482e+08 4.85165e+08
- 1.31882e+09 3.58491e+09 9.7448e+09 2.64891e+10 7.20049e+10 1.9573e+11
- EACH (exp (2+)) A
- 20.0855 54.5982 148.413 403.429 1096.63 2980.96
- 8103.08 22026.5 59874.1 162755. 442413. 1.2026e+06
- 3.26902e+06 8.88611e+06 2.4155e+07 6.566e+07 1.78482e+08 4.85165e+08
- 1.31882e+09 3.58491e+09 9.7448e+09 2.64891e+10 7.20049e+10 1.9573e+11
- Each transformers on two arguments
- A EACHLEFT f B applies f to pairs formed from the items of A and the argument B
- 3 4 5 EACHLEFT reshape "abc
- +-----------+---------------+-------------------+
- |abc abc abc|abc abc abc abc|abc abc abc abc abc|
- +-----------+---------------+-------------------+
- A EACHRIGHT f B applies f to pairs formed from the argument A and the items of B
- 3 4 EACHRIGHT reshape "abc "defg
- +---------------+-------------------+
- |abc abc abc abc|defg defg defg defg|
- |abc abc abc abc|defg defg defg defg|
- |abc abc abc abc|defg defg defg defg|
- +---------------+-------------------+
- A EACHBOTH f B applies f to pairs formed from the items of A and the items of B
- 3 4 EACHBOTH reshape "abc "defg
- +-----------+-------------------+
- |abc abc abc|defg defg defg defg|
- +-----------+-------------------+
- OUTER A OUTER f B computes applies f to the pairs formed from all combinations of
- the items of A with the items of B
- 3 4 5 OUTER reshape 'abcd'
- +-----+-----+-----+-----+
- |aaa |bbb |ccc |ddd |
- +-----+-----+-----+-----+
- |aaaa |bbbb |cccc |dddd |
- +-----+-----+-----+-----+
- |aaaaa|bbbbb|ccccc|ddddd|
- +-----+-----+-----+-----+
- The same result can be obtained by
- mix (A EACHLEFT EACHRIGHT f B)
- mix (3 4 5 EACHLEFT EACHRIGHT reshape 'abcd')
- +-----+-----+-----+-----+
- |aaa |bbb |ccc |ddd |
- +-----+-----+-----+-----+
- |aaaa |bbbb |cccc |dddd |
- +-----+-----+-----+-----+
- |aaaaa|bbbbb|ccccc|ddddd|
- +-----+-----+-----+-----+
Using array addresses
- Generating addresses
- The operation tell generates the 0-origin addresses for an array
- with the shape of the argument.
- tell 5
- 0 1 2 3 4
- tell 4 6
- +---+---+---+---+---+---+
- |0 0|0 1|0 2|0 3|0 4|0 5|
- +---+---+---+---+---+---+
- |1 0|1 1|1 2|1 3|1 4|1 5|
- +---+---+---+---+---+---+
- |2 0|2 1|2 2|2 3|2 4|2 5|
- +---+---+---+---+---+---+
- |3 0|3 1|3 2|3 3|3 4|3 5|
- +---+---+---+---+---+---+
- Selecting an item The operation I pick A selects the item of A at address I.
- 3 pick 'abcdef'
- d
- X := 34 15 -2 35 798
- 34 15 -2 35 798
- 1 pick X
- 15
- A := 4 6 reshape count 24
- 1 2 3 4 5 6
- 7 8 9 10 11 12
- 13 14 15 16 17 18
- 19 20 21 22 23 24
- 2 3 pick A
- 16
- There is an indexing notation for selecting an item using A@I where A is a variable.
- X@1
- 15
- A@(2 3)
- 16
- Selecting multiple items The operation I choose A selects the items of A at the addresses in I.
- 2 3 0 choose X
- -2 35 34
- [0 0, 1 1, 2 2, 3 3] choose A
- 1 8 15 22
- There is an indexing notation for selecting multiple items using A#I where A is a variable.
- X#(2 3 0)
- -2 35 34
- A#[0 0, 1 1, 2 2, 3 3]
- 1 8 15 22
- Selecting a slice of a table
- For convenience there is also a notation for selecting a row or column from a table variable
- A|[2,]
- 13 14 15 16 17 18
- A|[,3]
- 4 10 16 22
- Reaching into an nested array using a path
- B := rows A
- +-----------+--------------+-----------------+-----------------+
- |1 2 3 4 5 6|7 8 9 10 11 12|13 14 15 16 17 18|19 20 21 22 23 24|
- +-----------+--------------+-----------------+-----------------+
- 2 4 reach B
- 17
- There is an indexing notation for selecting along a pathusing A@@P where A is a variable
- B@@(2 4)
- 17
- Assigning into an array
- The variable selection notations can also be used to insert an item or items into an array.
- For example, to double the value at address 3 in X, use
- X@3 := x@3 * 2
- 34 15 -2 70 798
- To replace the diagonal items of A use
- A#[0 0, 1 1, 2 2, 3 3] := 1000 2000 3000 4000
- 1000 2 3 4 5 6
- 7 2000 9 10 11 12
- 13 14 3000 16 17 18
- 19 20 21 4000 23 24
- To negate the first row of A use
- A|[0,] := opp A|[0,]
- -1000 -2 -3 -4 -5 -6
- 7 2000 9 10 11 12
- 13 14 3000 16 17 18
- 19 20 21 4000 23 24
Unit 3: Nial examples
- Vector and matrix computations
- Building and using tables
- Executing strings
- Examples
Vector and matrix computations
- Scalars, Vectors, Matrices Nial represents scalars as numeric atoms, vectors as numeric lists,
- and matrices as numeric tables.
- We give some examples of linear algebra computations.
- Larger examples can be tried by changing the value of N.
- N := 4
- 4
- # Scalar S
- S := 3.14
- 3.14
- # Vectors X, Y
- X gets random N
- 0.633319 0.196128 0.329051 0.353133
- Y gets random N
- 0.0997199 0.993036 0.956765 0.351386
- # Matrices A and B
- A gets random N N
- 0.740653 0.156837 0.95601 0.652851
- 0.470182 0.342205 0.44016 0.761598
- 0.18367 0.946969 0.71337 0.605643
- 0.0498337 0.554176 0.0283656 0.740685
- B gets random N N
- 0.694195 0.340543 0.514273 0.388239
- 0.140726 0.177893 0.844948 0.0351305
- 0.438194 0.727605 0.858284 0.17794
- 0.63484 0.749474 0.416547 0.90947
- # Scalar times Vector
- S * X
- 1.98862 0.615843 1.03322 1.10884
- # Vector addition
- X + Y
- 0.733039 1.18916 1.28582 0.704518
- # item-by-item vector multiplication
- X * Y
- 0.0631546 0.194763 0.314824 0.124086
- # Vector inner product
- sum (X * Y)
- 0.696827
- # Scalar times Matrix
- S * A
- 2.32565 0.492468 3.00187 2.04995
- 1.47637 1.07452 1.3821 2.39142
- 0.576725 2.97348 2.23998 1.90172
- 0.156478 1.74011 0.089068 2.32575
- # Matrix Vector multiplication
- AX := EACH sum (rows A EACHLEFT * X)
- 1.04495 0.778671 0.750657 0.411144
- # Matrix Matrix multiplication
- AB := EACH sum (rows A OUTER * cols B)
- 1.3696 1.46502 1.60589 1.05692
- 1.05092 1.11205 1.22597 0.965537
- 0.957847 1.20397 1.75915 0.782327
- 0.595227 0.691318 0.826753 0.717494
- # solve linear equations A x = y
- A solve AX
- 0.633319 0.196128 0.329051 0.353133
- X
- 0.633319 0.196128 0.329051 0.353133
-
-
Building and using tables
- Data tables Nial does not directly support relational data bases and SQL style queries and updates.
- However, it is quite straightforward to build useful data tables and manipulate them.
- Consider an application in which records for employees are managed.
- These might be organized in a series of tables:
- Table 1 - Employee numbers, Employee names, Social Security number
- Table 2 - Employee numbers, Position, Department, Salary, Vacation allotment
- Table 3 - Employee numbers, Employment status, Vacation days used
- Table 4 - Employee numbers, Week number, Hours worked, Days missed for illness, vacation
- etc.
- Each table can be represented by a pair consisting of
- a list of column names and a data structure holding the data for the table.
- The data part can be organized in of three direct ways:
- - as a Nial table T where each row is one entry in the table,
- - as a nested list, rows T
- - as a nested list, cols T
- We choose the later representation for efficency of lookup and storage use.
- # the data base tables
- Tblnms := "EmpInfo "EmpPos "EmpData "WorkRecs
- EmpInfo EmpPos EmpData WorkRecords
- # list of column names for each table
-
- EmpInfoCols := "EmpNo "EmpNm "EmpSin
- EmpNo EmpNm EmpSin
- EmpPosCols := "EmpNo "Posn "Dept "Sal "VacDays
- EmpNo Posn Dept Sal VacDays
- EmpRecCols := "EmpNo "Status "VacUsed
- EmpNo Status VacUsed
- WorkRecsCols := "EmpNo "WeekNo "Hours "SickDays "VacDays
- EmpNo WeekNo Hours SickDays VacDays
- # sample data for each table
- EmpInfoData := flip
- [100 'John Smith' 235648329,
- 201 'Pat Johnson' 384263549,
- 128 'Mary Armstrong' 653902194
- ]
- +-----------+---------------------------------------+---------------------------
- |100 201 128|+----------+-----------+--------------+|235648329 384263549 6539021
- | ||John Smith|Pat Johnson|Mary Armstrong||
- | |+----------+-----------+--------------+|
- +-----------+---------------------------------------+---------------------------
- --+
- 94|
- |
- |
- --+
- EmpPosData := flip
- [100 "Pres "Admin 235000 30,
- 201 "Salesperson "Marketing 85000 20,
- 128 "AdminAsst "Marketing 45000 15
- ]
- +-----------+--------------------------+-------------------------+--------------
- |100 201 128|Pres Salesperson AdminAsst|Admin Marketing Marketing|235000 85000 4
- +-----------+--------------------------+-------------------------+--------------
- ----+--------+
- 5000|30 20 15|
- ----+--------+
- EmpRecData := flip
- [100 "Active 3,
- 201 "Active 5,
- 128 "active 12
- ]
- +-----------+--------------------+------+
- |100 201 128|Active Active active|3 5 12|
- +-----------+--------------------+------+
- WorkRecsData := flip
- [100 10 45 0 0,
- 201 10 35 0 2,
- 128 10 40 1 0,
- 100 11 45 0 0,
- 201 11 35 1 0,
- 128 11 40 1 1
- ]
- +-----------------------+-----------------+-----------------+-----------+-------
- |100 201 128 100 201 128|10 10 10 11 11 11|45 35 40 45 35 40|0 0 1 0 1 1|0 2 0 0
- +-----------------------+-----------------+-----------------+-----------+-------
- ----+
- 0 1|
- ----+
- routines to support table computations
- # routine to display a table
- displaytbl IS OP Nms Data {
- mix flip (Nms EACHBOTH hitch Data) }
- displaytbl WorkRecsCols WorkRecsData
- EmpNo WeekNo Hours SickDays VacDays
- 100 10 45 0 0
- 201 10 35 0 2
- 128 10 40 1 0
- 100 11 45 0 0
- 201 11 35 1 0
- 128 11 40 1 1
- # routine to select a single record in a table by Key (first column)
- getrec IS OP Key Data {
- Pos := Key find first Data;
- Pos EACHRIGHT pick Data }
- getrec 128 EmpInfoData
- +---+--------------+---------+
- |128|Mary Armstrong|653902194|
- +---+--------------+---------+
- # expression to get all entries in a table by Key
- getrecs IS OP Key Data {
- Posns := Key findall first Data;
- Posns EACHLEFT EACHRIGHT pick Data }
- getrecs 201 WorkRecsData
- +-------------+-------------+
- |201 10 35 0 2|201 11 35 1 0|
- +-------------+-------------+
- # routine to update a record in a data table
- updateFld IS OP Tbl Key Fld Val {
- TblCols TblDataNm := Tbl;
- Data := value TblDataNm;
- I := Key find first Data;
- Fld_I := Fld find TblCols;
- deepupdate TblDataNm [Fld_I,I] Val }
-
- # assignment to update salary by employee name
-
- updatesalary IS OP EmpName NewSalary {
- Posn := EmpName find second EmpInfoData;
- EmpNo := Posn pick first EmpInfoData;
- updateFld (EmpPosCols "EmpPosData) EmpNo "Sal NewSalary; }
-
- # table before update
- displayTbl EmpPosCols EmpPosData
- EmpNo Posn Dept Sal VacDays
- 100 Pres Admin 235000 30
- 201 Salesperson Marketing 85000 20
- 128 AdminAsst Marketing 45000 15
- updatesalary 'Mary Armstrong' 48000;
- # table after update
- displayTbl EmpPosCols EmpPosData
- EmpNo Posn Dept Sal VacDays
- 100 Pres Admin 235000 30
- 201 Salesperson Marketing 85000 20
- 128 AdminAsst Marketing 48000 15
-
Executing strings
- Evaluating a constructed string
- One of the many advantages of interpretation is that
- one can easily evaluate expressions that are constructed on the fly.
-
- Choice := 2
- 2
- Nms := 'W' 'X' 'Y' 'Z'
- +-+-+-+-+
- |W|X|Y|Z|
- +-+-+-+-+
- Arg := 5
- 5
- Expr := link Nms@Choice ' := count ' (string Arg) ';'
- Y := count 5;
- execute Expr
- Y
- 1 2 3 4 5
Examples
- Delete all blanks from a string.
- deleteblanks IS OP Str {
- not (Str match ` ) sublist Str }
- deleteblanks ' Where did all the flowers go. '
- Wheredidalltheflowersgo.
- Set manipulation examples
- # subset test
- subset IS OPERATION A B { and ( A EACHLEFT in B ) }
- 'abc' subset 'qwertyckdsba'
- l
- # intersection
- intersect IS OPERATION A B {
- EACH and ( A EACHLEFT EACHRIGHT in A B ) sublist A
- }
- Friends := "Mary "Ludwig "Hercule "Tom "Sarah ;
- Pals:= "Jack "Tony "Rick "Tom "Kalev;
- Friends intersect Pals
- Tom
- Moving average
- Compute the moving average of length N for an array Data
- moving_average IS OPERATION N Data {
- Indicies := tell (tally Data - N + 1) EACHLEFT + tell N;
- Groups := Indicies EACHLEFT choose Data;
- EACH sum Groups / N }
- 2 moving_average 3 4 5 6 7 8
- 3.5 4.5 5.5 6.5 7.5
- Count occurences
- # This operation counts the number of occurrences in A of each value in
- Values.
- frequency IS OPERATION Values A {
- EACH sum ( Values EACHLEFT EACHRIGHT = A ) }
- frequency 'abc' 'The cat sat on the baseball bat'
- 5 3 1
- # If the items of Values are know to be atomic then a faster version is:
- atfrequency IS OPERATION Values A {
- EACH sum ( Values EACHLEFT match A ) }
- atfrequency 'abc' 'The cat sat on the baseball bat'
- 5 3 1
- Prime numbers <= N
- # use sieve algorithm, where candidates are removed when they are multiples
- of primes already found.
- # uses implicit loops except for controlling WHILE loop of indefinite length
- sieve IS OPERATION N {
- Candidates := rest count N;
- Primes := Null;
- WHILE not empty Candidates DO
- Primes := Primes append first Candidates;
- Candidates := not (Candidates mod first Candidates match 0)
- sublist Candidates;
- ENDWHILE;
- Primes }
- sieve 100
- 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
- Frequency of prime numbers
- # count occurences in ranges
- countinranges IS OP Vals RangeVals {
- inrange IS OP V Rng {
- V > first Rng and (V <= last Rng) };
- Ranges := front Rangevals EACHBOTH pair rest Rangevals;
- EACH sum (Vals EACHRIGHT EACHLEFT inrange Ranges) }
- # 10 ranges of length 10
- sieve 100 countinranges (10 * tell 11)
- 4 4 2 2 3 2 2 3 2 1
- # 10 ranges of length 100
- sieve 1000 countinranges (100 * tell 11)
- 25 21 16 16 17 14 16 14 15 14
- # 10 ranges of length 1000
- sieve 10000 countinranges (1000 * tell 11)
- 168 135 127 120 119 114 117 107 110 112
- # 100 ranges of length 100
- sieve 10000 countinranges (100 * tell 101)
- 25 21 16 16 17 14 16 14 15 14 16 12 15 11 17 12 15 12 12 13 14 10 15 15 10 11 15
- 14 12 11 12 10 11 15 11 14 13 12 11 11 15 9 16 9 11 12 12 12 8 15 12 11 10 10 1
- 3 13 12 10 16 7 12 11 13 15 8 11 10 12 12 13 9 10 11 9 11 15 12 10 10 10 11 10 1
- 4 9 8 12 13 11 13 9 11 12 11 11 15 7 13 11 12 9