Chapter 3
A closer look at some types:
This type has a single value, or rather non-value,
also called
nil . It is returned by a function with no
return statement, and given by any variable
that has not had a value assigned to it. It is different
from any other value.
This type has just two values,
false and
true . The following
comparison operators,
applied to strings (lexicographic ordering) or numbers,
give a boolean result. They are:
== equals
~= not equals
< less than
> greater than
<= less than or equal
>= greater than or equals
There are places where non-boolean values must be treated
as booleans. Non-nil non-boolean values are treated as
true (including zero and the empty string),
nil is treated as
false . This
coercion process takes place
after the words
if elseif not until while
and for the first argument of
and and
or .
These two words can be used in a very flexible concise way.
The expression
x and y evaluates to
y if
x is non-nil or
true , and to
x , without evaluation of
y , otherwise.
The expression
x or y evaluates to
y if
x is
nil or
false , and to
x , without evaluation of
y , otherwise.
So
c and a or b
gives
a if
c is
true and
b if
c is
false . This notation is very useful
for dealing with situations where you are unsure whether
data loaded by the program actually exists, and you want
alternative default data to be used if it does not. For example,
for a list of speakers and titles for a usergroup lecture
you might have:
print (title or "To be announced")
Numbers in RiscLua are 32-bit integers, between -2147483648 and
2147483647. They can also be entered in hexadecimal notation
with prefix 0x,
from 0x00000000 to 0xffffffff. The operations of addition,
subtraction and multiplication modulo the 32nd power of 2 are
given by the usual symbols
+ - * . The
operation
/ gives the integer result obtained
by rounding towards zero. On the other hand, the
modulus operator
% always gives a positive
answer, the least non-negative integer in the residue class of
the first argument modulo the second. The exponentiation operator
is
^ . Its second argument must not be negative.
RiscLua adds the following bitwise operators:
& bitwise AND
| bitwise OR
^^ bitwise XOR
~ bitwise NOT
<< shift bits left
>> arithmetic shift bits right
Standard Lua uses 64-bit floating point numbers (
doubles) by default, but, for reasons of efficiency
and interfacing to RISC OS, RiscLua uses 32-bit integers.
In fact RiscLua does let you use doubles but in rather a
different way. You create a double with the
@ function.
x = @(560) -- from an integer
y = @'0.3333' -- from a string
z = @(x) -- from a double
Note that if
x is a double
print(type(x)) --> userdata
The operator
# does its best to produce
an integer number out of a a double.
x = @'2.3'
y = #x
print(type(y)) --> number
print(y) --> 2
The arithmetic operators
+ - * / give a double
if one of the operands is a double. In this case division is not rounded
to an integer, of course.
What is the difference between
z = @(x) and
z = x ? That there is a difference is because doubles
are actually
objects (stored in the
heap) and not values. In the first case
z is a separate object, whose value is copied from
that of
x . In the second case
z and
x are different names
for the same object. Update one and you update
the other.
x = @'0.5'
y = x
z = @(x)
x:add(7)
print(y) --> 7.5
print(z) --> 0.5
Here we see a new notation, the colon (
: ) which attaches a
method to a variable
denoting an object.
Doubles have the following methods supplied in the
dbl library:
x:add(y) -- add y to x
x:sub(y) -- subtract y from x
x:mul(y) -- multiply x by y
x:div(y) -- divide x by y
x:ldexp(n) -- multiply by 2^n where n is of type number
x:abs() -- replace x by its absolute value
x:ceil() -- replace x by the least whole number bigger
x:floor() -- replace x by the greatest whole number less
x:sin() -- apply sin to x
x:cos() -- apply cos to x
x:tan() -- apply tan to x
x:sinh() -- apply sinh to x
x:cosh() -- apply cosh to x
x:tanh() -- apply tanh to x
x:asin() -- apply arcsin to x
x:acos() -- apply arccos to x
x:atan() -- apply arctan to x
x:inv() -- invert x
x:sqrt() -- square root x
x:exp() -- exponentiate x
x:log() -- apply logarithm to x
Methods update a double, they do not create a new
object. To create a new object either use
@ or
an arithmetic operation.
x = @(1)
y = @(2)
z = x + y
x:add(10)
print(z) --> 3
print(x + y) --> 13
There are two ways of denoting strings in Lua:
single line or
multiline.
Single line strings are enclosed in doublequotes (
" ) or in singlequotes (
' ). You can
use a doublequote inside a singlequoted string and a
singlequote inside a doublequoted string. The character
\ is an
escape character for
single line strings. So you can use
\" and
\' to denote quotes in either kind of string.
You can use
\n to denote a newline. Newlines
themselves cannot occur in single line strings. The backslash
character must itself be escaped, i.e. written as
\\ , inside quoted strings.
A multiline string can contain newlines, but
\ does not behave as an escape character inside it. It
begins with a pair of open square brackets (
[ ) separated by however many equal signs (
= ) you want, possibly none. If the next character
is a newline, it is disregarded. It ends with a pair of close
square brackets separated by the same number of equal signs.
print("A"..'B'..[[C]]..[=[D]=]) --> ABCD
The operator
.. concatenates strings. The
operator
# gives the length of a string.
x = "hello"
print(#x) --> 5
If a comment sign is followed immediately by a multiline
string, then the comment is that string. This gives a facility
for multiline comments. A neat trick for commenting out a piece
of code is:
--[=[
foo = blah -- commented out
. . . .
--]=]
Then, to uncomment the code, simply slip an extra minus sign in
at the front.
---[=[
foo = blah -- no longer commented out
. . . .
--]=]
Now the
-[=[ is itself commented out.
Strings also support the colon notation.
s = "Basil_of_Bithynia"
print(s:sub(7)) --> of_Bithynia
print(s:sub(-8)) --> Bithynia
print(s:sub(1,5)) --> Basil
To use the colon notation with a literal string or a complex
expression evaluating to a string, the expression for the string
must be in parentheses.
print(("%d is 0x%x in %s"):format(10,10,"hexadecimal"))
The
sub method selects substrings. Note that negative
indices count from the end of the string. The
format method formats a string using
formatting specifiers as used in C.
Strings in Lua are immutable objects, like numbers (but unlike
doubles). Identical strings are held in identical storage,
so testing string equality is fast, and independent of the
size of the strings, being a matter of comparing two
addresses. Strings can be of any length, depending on the
memory available. They can contain characters
of any ASCII value. Unlike C, ASCII NUL does not play the role
of a terminator. So it is quite possible to load largish files
in as strings.
If a literal string (i.e. not a variable or complex expression
evaluating to a string) is the single argument to a function
the parentheses can be omitted. That is why we may write
x = @'3.3333'
print "bother"
print [[
A sagitta volente per diem
A negotio perambulante in tenebris]]
instead of
x = @ ('3.3333')
print ("bother")
print ([[
A sagitta volente per diem
A negotio perambulante in tenebris]])