Expressions and Operations

This lesson is a bit "academic" so prepare a cup of tea or coffee to go through it calmly and attentively :)

We have already vague understanding that there could be numbers and strings, they could be assigned to variables and also added, subtracted, multiplied etc. It's time to quickly "formalize" this knowledge.

You remember we agreed to call statements small pieces of code which instruct machine to execute some action.

Now expressions are smaller pieces, often parts of statements, which express or calculate some value. Regard an example:

print(3+5*4)

the whole line is a statement, which prints the result of expression 3+5*4. But what if we print a simple string in quotes (i.e. text constant, or "literal"):

print('hafanana')

in this case 'hafanana' is an expression anyway. In more general terms expression consists of values joined by operators. Values could be represented by variables or constants.

Operators are all those +, -, and so on. We'll get more details in a few minutes. But now let's talk about types.

About Types

Let's regard constant expressions more closely. We already found they could be like text or like numbers. Sometimes we found they do not always suit each other. For example:

print(10 * 'xo')

this throws an error like attempt to mul 'number' with 'string'. So strings seemingly couldn't be multiplied.

Now we understand any value has some type - and by the way this could be detected using type(...) function:

print(type(10))
print(type('blaha'))

These print number and string respectively. But the language has more than just two types. Try this line:

print(10 == 8, 10 == 10, type(10 == 5))

You'll see three results false, true and boolean. So all these "comparison operators" like equality return special type boolean, which has only two values - these "true" and "false" (you can use them in your program literally).

The value of boolean type is usually expected inside if ... then or while ... do constructs.

Small List of Operators

Operations on numbers

We already understand there are +, -, * and /, as in kid's school. There are few more handy operations - try these lines:

print(8 / 3)    -- general division
print(8 // 3)   -- integer division

You'll see 2.666...67 and simple 2. The second version of division throws away any fractional part.

print(100 % 3)  -- remainder
print(3^4)      -- raising to power

Operations on strings

By now we know only one string operation - concatenation, and that's enough. Other string manipulations are done with special functions instead, we'll learn of them later.

print('10' .. '10')

Note that integer values are treated as text because they are surrounded with quotes and string concatenation operator is applied to them. Hence the result 1010 (rather than 20).

Comparison operators

These are interesting. They use as operands other types, like numbers or strings, and their result is boolean (true or false):

print('bla' == 'mla')    -- is the first equal to second?
print(5 > 3)             -- is greater than?
print(5 >= 2+3)          -- is greater or equal?
print(2^3 < 10)          -- is less than?
print(100%9 <= 1)        -- is less or equal?
print(100 // 10 ~= 10)   -- is not equal

Boolean operators

Sometimes we need to check more than one condition, like we want to know if user entered yes or ja (perhaps, user is German?). In other case we want to know if user is no less than 18 and no more than 100 years. These are achieved with operations or, and respectively:

print('enter "yes" or "ja":')
response = io.read('*l')
print(response == 'yes' or response == 'ja')

print('enter your age:')
age = io.read('*n')
print(age >= 18 and age <= 100)

There is also handy operation not, which inverts logical value following it. Just be careful with it, see below.

Exercise

As Lua language wants to be user-friendly, it allows in some cases to automatically convert values of different types to match those wanted by operators. For example:

print(10 + 'SO')    -- error
print(10 + '50')    -- gives 60

so if we try numeric addition on a string, which could be converted to number, it works all right!

For exercise try some other cases to see when auto-conversion works. Explain the results:

print('5' * '5')
print(10 + '-3e1')
print('five is ' .. 5)
print('true is ' .. true)
print(10 == '10')
print(not 10 == 8)
print(not (10 == 8))

The last two lines could be confusing. Obviously not 10 is executed first (and what is result?) and then only compared to 8. Thus the parentheses are necessary for proper calculation order.

Double not would simply convert value to logical, retaining its "logical meaning" so to say. Play a bit more with it to see how different values are converted:

print(not not true)
print(not not false)
print(not not 10)
print(not not '10')
print(not not 0)
print(not not '0')
print(not not nil)

You should find that only one of non-boolean values is treated like false.