Slang is a *s*imple programming *lang*uage. It has elements of L__I__S__P, Python and B__A__S__I__C to it, but of course is quite superior to these.
= Introduction
Slang is a simple programming language, designed to be simple enough for people who have no prior knowledge of programming, but powerful enough for people who do. It strives for that kind of simplicity which removes obstacles from the programmer's route without removing the route itself, and which is most evident in languages like L__I__S__P. Indeed, although L__I__S__P was not a direct influence on the design of slang, the two have come out rather similar (despite having very different syntax).
= Kinds of Computational Objects
There are five kinds of object in the computational universe of slang:
- Integers
- Real numbers ('reals')
- Strings
- Lists
- Blocks
Each of these is dealt with in detail below.
== Integers
An integer does exactly what it says on the tin: it is a positive or negative whole number, written in the usual way (a string of decimal digits):
$
0
1
23
-5
27489257
Integers are mostly useful as 'counting numbers', for things like measuring the number of some things, or representing a position in a sequence, etc. They are the workhorse of program arithmetic.
Integers are also used to represent the truth values 'true' and 'false'; 0 stands for false, and any nonzero number (conventionally 1) for true.
== Reals
Real numbers are also what they sound like: they can have fractional parts. They are written like integers, but with a decimal point and some trailing digits:
$
1.0
3.14159
-2.4
Note that the decimal point is essential; without it, a number is treated as an integer. Note also that there must be at least one digit on either side of the decimal point; 1. and .5 are not allowed!
Furthermore, reals can be written in scientific notation ('a times ten to the b'), by following a real as described above with a letter 'e' (upper or lower case) and an integer literal (with no intervening spaces); the trailing integer represents the exponent (the bit after 'times ten to the'). For example:
$
3.0e8
6.023e23
10.0e-6
Which are the speed of light (in m/s), Avogadro's constant, and the concentration of tris in T__E (in mol/l), respectively.
Reals are useful for handling numbers which are being computed with, for example in a scientific program.
== Strings
A string is a piece of text, or more formally, a sequence of characters; it could be anything from a single character (or even no characters) to an entire book. A string is written by surrounding the characters of the string with speechmarks:
$
""
"a"
"hello"
"The cat sat on the mat."
Note that the first example above is a string with no characters at all; this is commonly known as 'the empty string' or 'the null string'.
Note that you run into trouble if you try to include certain characters in your strings: the speechmark is an obvious one, as it will bring your string to a premature conclusion; carriage returns will also cause trouble. Handily, you can enter troublesome characters using 'escape sequences': an escape sequence is a backslash followed by some other letter (the 'escape code'), and corresponds to some other, troublesome, character. The most important escape codes are " (meaning a speechmark), \ (meaning a backslash), t (meaning a tab) and n (meaning a newline). The complete set of escapes is given below.
| Code | Normal meaning | Escaped meaning |
| " | End of string | "
| \ | Start escape sequence | \
| t | t | Tab
| v | v | Vertical tab (?!?)
| r | r | Carriage return
| l | l | Linefeed
| n | n | Local newline (C__R on Mac, L__F on Unix, C__R L__F on Windows)
| f | f | Form feed
| b | b | Backspace
| 0 | 0 | Null (A__S__C__I__I 0)
| ^ | ^ | Escape character (A__S__C__I__I 33)
| a | a | Alarm bell (makes the terminal beep!)
| + | + | Starts a unicode hex sequence (eg \+0020 for a space)
| . | . | End of file (A__S__C__I__I 4; like ^D in Unix)
If any other character follows a backslash, it simply means itself. So, the string "\"Hello\n\tWorld!\"\n\a" would correspond to the text:
$
"Hello
World!"
And the terminal would beep at the end.
== Lists
A list is simply a sequence of other objects. It is written as a comma-separated sequence of things enclosed in square brackets:
$
[]
[1, 2, 3]
[23, "skidoo"]
["element number", "2", ["is", "a", "list"]]
Note that the elements in lists are numbered starting at 0.
== Blocks
A block is a chunk of program code; it is written by enclosing the code in curly brackets:
$
{}
{ foo }
{ foo ; bar }
The nature of code and blocks will be dealt with later.
= Expressions
An expression is a thing with a value (where a value is one of the computational objects defined above); expressions are the atoms of a program, the simplest units out of which everything else is built. There are three kinds of expressions:
- Literal
- Reference
- Compound
= Literal Expressions
A literal expression, or just 'literal', is simply a written-out value of some object. For example, a few literal expressions are:
$
1
3.14159
"Hello world!"
[1, 2, 3]
{ foo }
Nice and easy!
= Reference Expressions
Slang is able to attatch a name to a particular object; that name then stands for that object. The name can later be attatched to other objects, after which it stands for those instead. For example, say that the name "alpha" was associated with the number 23; one legitimate reference expression would then be:
$
alpha
The value of this expression would be 23.
= Compound Expressions
A compound expression consists of an operator and two operands, surrounded by parentheses; an operator is a symbol standing for some computational operation, and the operands are expressions of any type. The value of such an expression is the value of that operation carried out on the operands. For example, these are all compound expressions whose meaning should be clear (provided you know that * means multiplication and / means division):
$
(1 + 1)
(4 * 6)
(55.0 + 0.8)
(2.0 - 1.5)
(8.9 / 34.0e-6)
(2.0 * (1.5 + 0.7))
((alpha * 2.0) - (alpha * alpha))
There is a different set of operators for each kind of object, and these are listed below. In addition, there are a few 'unary' operators, which operate on just one operand (which is written after the operator); these are also shown below.
When an expression has different kinds of object on either side, one of the operands is adjusted to match the other. The way this works is that the types are organised into a hierarchy (from top to bottom: block, list, string, real, integer), and the inferior operand is 'promoted' to the type of the superior one. Values are promoted in fairly obvious ways:
- An integer is promoted to a real with the same value (eg 5 -> 5.0)
- Numbers are promoted to strings corresponding to the textual representation of the number (eg 5 -> "5", 3.14159 -> "3.14159")
- Things are promoted to lists by construction of a list containing just that thing (eg 5 -> [5], 3.14159 -> [3.14159], "sausages" -> ["sausages"])
- Things are promoted to blocks by construction of a block which evaluates to that thing (this will make sense when you understand blocks! eg 5 -> { 5 } etc)
= Integer Operators
: + : Addition
: - : Subtraction
: : Multiplication
: / : Division (rounding down, eg (5 / 3) -> 1)
: % : Remainder (the bit thrown away in division, eg (5 % 3) -> 2
: : Exponentiation ((a b) computes a to the power of b)
: & : Logical A__N__D
: | : Logical O__R
: ^ : Logical X__O__R
: && : Bitwise A__N__D
: || : Bitwise O__R
: ^^ : Bitwise X__O__R
Unary:
: - : Negation
: + : Absolute value
: -- : Incrementation (eg (++1) -> 2)
: ++ : Decrementation (eg (--1) -> 0)
: ! : Logical N__O__T
: !! : Bitwise N__O__T
= Real Operators
: + : Addition
: - : Subtraction
: : Multiplication
: / : Division
: : Exponentiation ((a b) computes a to the power of b)
Unary:
: - : Negation
: + : Absolute value
: / : Square root
= String Operators
: + : Concatenation (eg ("a" + "b") -> "ab")
: @ _integer_ : Extraction (the character at the position given by the second operand is extracted, eg ("abcdef" @ 2) -> "c")
: = _object_ : naming (attatches a name (which must start with a letter and contain only letters, numbers and underscores) to a value of some sort; its value is the value of the named object, eg ("alpha" := 23) -> 23)
: ~ : Matching (matches the left-hand operand against the regular expression defined by the right-hand; the value is a list containing the matched string, followed by any captured subexpressions, or the empty list if there is no match, eg ("there were 10 green bottles, hanging on the wall" ~ "([0-9]+) [a-z]+ bottles") -> ["10 green bottles", "10"])
Note that the naming operator, :=, is incredibly important.
Unary:
: $ : Size (number of characters)
= List Operators
: + : Concatenation (eg ([1] + [2]) -> [1, 2])
: @ _integer_ : Extraction (the element at the position given by the second operand is extracted, eg (["a", "b", "c", "d", "e", 'f"] @ 2) -> "c")
Unary:
: $ : Size (number of elements)
= Comparison Operators
These operators can be applied to any of the integer, real, string and list types.
_==, <, <=, >, <=, <>, <=>_
= Block Operators
: _list_: Execution (yes, there is no actual operator symbol; executes the block, with the list as an argument, eg (log10 100.0) -> 2.0, (mean [1.0, 2.0]) -> 1.5)
The execution operator is another fundamentally important operator.
= Programs
A block consists of a sequence of statements (from which the outermost parentheses can be omitted), separated by semicolons and surrounded by curly brackets. When the block is evaluated, the statements are evaluated one after the other, and the value of the last statement is used as the value of the block.
A program is a block, from which the curly brackets can be omitted.
Yes, that's all.
How do you build complex applications out of, ultimately, just expressions? Well, there are two particular operators that you will end up using a lot, and some predefined names which haven't been mentioned yet.
The crucial operators are naming (:=) and execution (the no-symbol operator!). These are what give programs structure. For example:
$
"double_a" := { (a * 2) } ;
"a" := 10 ;
double_a []
The above program will compute the number 20, and then finish.
There are two sets of crucial predefined names, plus one not-so-crucial set.
The first are the argument names; when a block is executed, an argument list is supplied: inside the block, this list can be found under the name , and, for convenience, its elements under the names 0, 1, etc. For example:
$
"double" := { (_0 * 2) }
double [ 10 ]
This program will also compute the number 20 and then finish.
The second is the control flow blocks; these are names attatched to magic blocks which operate primarily on other blocks. The two most important control blocks are called "if" and "while". "if" takes an integer and a block; if the integer is true (nonzero), the block is executed with an empty list as an argument. "while" takes two blocks; it executes the first block, and if it is true, executes the second, and then goes round again. Other control blocks include "choose" and "case". For example:
$
"a" := 0 ;
"sum" := 0 ;
while [{a < 10}, {
"sum" := (sum + a) ;
"a" := ++a ;
}]
This program computes the sum of the numbers from 0 to 9. Note the use of whitespace for layout.
There is a third set of predefined names, which provide useful utility functions, including some particularly handy ones for getting data into and out of programmes. Together, these are known as the library.
= The Library
= Mathematics
: e : Euler's constant (2.7...)
: pi : pi (3.14159)
: log [_n_, _b_] : computes the logarithm of _n_ to the base _b_
: ln [_n_] : computes the natural logarithm of _n_
: log10 [_n_] : computes the logarithm of _n_ to the base 10
: sin [_theta_] : computes the sine of the angle _theta_
: cos [_theta_] : computes the cosine of the angle _theta_
: tan [_theta_] : computes the tangent of the angle _theta_
: sinh [_theta_] : computes the hyperbolic sine of the angle _theta_
: cosh [_theta_] : computes the hyperbolic cosine of the angle _theta_
: tanh [_theta_] : computes the hyperbolic tangent of the angle _theta_
: asin [_r_] : computes the arcsine of the ratio _r_
: acos [_r_] : computes the arccosine of the ratio _r_
: atan [_r_] : computes the arctangent of the ratio _r_
: asinh [_r_] : computes the hyperbolic arcsine of the ratio _r_
: acosh [_r_] : computes the hyperbolic arccosine of the ratio _r_
: atanh [_r_] : computes the hyperbolic arctangent of the ratio _r_
All angles are measured in radians.
= Strings
: substr [_s_, _off_, _len_] : returns the substring of _s_ starting at _off_ and extending for _len_ characters
: explode [_s_] : returns _s_ as a list of characters (eg explode["apple"] -> ["a", "p", "p", "l", "e"]
: collapse [_l_] : collapses the list _l_ into a string (non-string elements are stringified first)
= Lists
: flatten [_l_]: flattens any nested lists inside _l_ (eg flatten [1, 2, [31, 32, 33], [[4]]] -> [1, 2, 31, 32, 33, 4])
= Conversion
: type [_x_] : gets a string representation of the type of _x_: one of "integer", "real", "string", "list" and "block"
: integer [_x_] : converts some thing to an integer; reals are rounded, strings are parsed, lists are treated as their last element
: real [_x_] : converts some thing to a real; integers are promoted, strings are parsed, lists are treated as their last element
: string [_x_] : converts some thing to a string; integers and reals are promoted, lists are treated as their last element
: list [_x_] : converts some thing to a list; integers, reals and strings are promoted
= Input and Output
: print [_s_] : prints a string to the terminal, followed by a newline
: scan : reads a string from the terminal, terminated by a newline