title logo

back contents forward

Chapter 3

A closer look at some types:

nil

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.

booleans

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:

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

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

strings

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]])


back contents forward