User:SuzannaLinn Resident/LuaLanguage1

From Second Life Wiki
Jump to navigation Jump to search

The language: Lua compared to LSL

Standard Lua and Luau have some differences. Most of the next code runs in both of them. I'm using "Luau" at the end of the comment in the first line for Luau only code. I'm using "LuaSL" for presumed LuaSL only code.

Types and variables

-- types and variables (Lua)

isOn = true
myCounter = 10
myMessage = "Hello"

print( type( isOn ) )       -- boolean
print( type( myCounter ) )  -- number
print( type( myMessage ) )  -- string

myMessage = myCounter
print( type( myMessage ) )  -- number

myMessage = tostring( myCounter )
print( type( myMessage ) )  -- string
// types and variables (LSL)

integer isOn = TRUE;
integer myCounter = 10;
string myMessage = "Hello";








myMessage = (string)myCounter;

Comments use -- instead of //

The semicolon at the end of the lines is optional and very rarely used.

Variables are not declared with a type, they can take values of any type.

Their type depends on what value we assign to them.

We can see it in lines 7-9. The function "type" returns the name of the type and "print" outputs it to the console. I have added the text printed as a comment.

These are the three basic types: "boolean" (true of false), "number" (which includes integers and floats) and "string".

There are no types key, vector or rotation. LuaSL will add them. A vector, for instance, could be like:

   colorRed = vector(1, 0, 0)        instead of:   vector colorRed = <1, 0, 0>;

We can assign any value to any variable, like in line 11, assigning a number to a variable that had a string changes the variable type to number.

If we want to have it as a string we need to typecast it, as in line 14.

Variables that can have any type are very useful sometimes but can lead to errors.

Luau adds capabilities of Type-checking and Linting, that LuaSL will also have:

- Type checking automatically infers types from the values assigned to variables or manually by adding type annotations. These annotations can define types, combinations of types, or subtypes. There are directives that allow to control the level of type checking in each script, ranging from none to stricter than LSL.

- Linting identifies possible issues like uninitialized or unused variables, duplicated functions, mismatched parameter counts, return values, and many more. There are also directives to enable or disable specific linting checks.


Operators

-- operators (Lua)

-- +, -, *, % (modulus) are the same
print( 7 / 4 )   -- 1.75
print( 7 // 4 )  -- 1
print( 2 ^ 3 )   -- 8

-- ==, <, >, <=, >= are the same
print( "hello" ~= "bye" )  -- true    ( ~ is Alt+126 )

isOn = true
myCounter = 10
myMessage = "hello"

print( isOn and myCounter == 0 )  -- false
print( isOn or myCounter == 0 )   -- true
print( not isOn )                 -- false

print ( myMessage.." world" ) -- hello world
print( #myMessage )           -- 5

-- ++, -- doesn't exist
myCounter = myCounter + 1

-- +=, -=, *=, /=, %= doesn't exist
myCounter = myCounter + 5
// operators (LSL)

// +, -, *, % (modulus) are the same
llSay(0, (string)( 7.0 / 4.0 ) );       // 1.75
llSay(0, (string)( 7 / 4 ) );           // 1
llSay(0, (string)llPow( 2, 3 ) );   // 8

// ==, <, >, <=, >= are the same
llSay(0, (string)( "hello" != "bye" ) );  // 1

integer isOn = TRUE;
integer myCounter = 10;
string myMessage = "hello";

llSay(0, (string)( isOn && myCounter == 0 ) );   // 0
llSay(0, (string)( isOn || myCounter == 0 ) );   // 1
llSay(0, (string)( !isOn ) );                    // 0

llSay(0, myMessage + " world" );         // hello world
llSay(0, (string)llStringLength( myMessage ) );  // 5

// ++, //
myCounter++;

// +=, -=, *=, /=, %=
myCounter += 5;

There are some differences in the operators.

The / is the float division. There is the // that is the integer division.

There is an exponentiation operator, ^.

The unequality operator is ~= instead of !=.

&&, ||, ! are "and", "or", "not"

The concatenation operator is .. instead of +. This is because of the changing types of the variables, it needs to be clear what operation we want to do.

The # returns the length of a string.

The increment and decrement operators, ++ and --, doesn't exist.

The compound operators, += and so on, doesn't exist in standard Lua, but they exist in Luau, so probably LuaSL will have them: +=, -=, *=, /=, //=, %=, ^=.


If, while, for, repeat

-- If, while, for, repeat (Lua)

counter = 3


if counter == 1 then

elseif counter == 2 then

else

end


while counter > 0 do
    counter = counter - 1
end


for i = 0, 10, 2 do
    print( i )  -- 0, 2, 4, 6, 8, 10
end


repeat
    counter = counter +1
until counter == 5
// If, while, for, repeat (LSL)
integer i;
integer counter = 3;


if (counter == 1) {

} else if (counter == 2) {

} else {

}


while (counter > 0) {
    counter--;
}


for ( i = 0; i < 11; i+=2 ) {
    llSay(0, (string)i );  // 0, 2, 4, 6, 8, 10
}


do
    counter++;
while (counter < 5);

There are the same blocks if, while and for. And a repeat..until instead of do...while ("repeat..until not" is the same as "do...while").

The { and } are not used here (they are used for tables as we will see later). Instead there are keywords, "then" or "do", and "end".

The "for" in lines 20-22 is one of the types of "for", we will see the other one later. Its 3 values are start, end and step.

We can't use an assignment in a condition. In lua assignments are statements, not expressions.

In case that we write a = instead of a == in a condition, we will get an error when compiling.


Functions, ll functions

-- Functions, ll functions (Lua)

function average( a, b )
    return ( a + b ) / 2
end

print( average( 15, 5 ) )  -- 10
-- ll.Say( 0, average( 15, 5 ) )


function factorial( n )
    if n < 0 then
        return nil
    elseif n == 0 then
        return 1
    else
        return n * factorial( n - 1 )
    end
end

number = 5
result = factorial( number )

if result ~= nil then 
    print( "Factorial of "..number.." is "..result )  -- Factorial of 5 is 120
else
    print( number.." is not valid")
end
// Functions, ll functions (LSL)

float average( float a, float b ) {
    return ( a + b ) / 2;
}

llSay(0, (string)average( 15, 5 ) );  // 10



integer factorial( integer n ) {
    if (n < 0) {
        return -1;
    } else if (n == 0) {
        return 1;
    } else {
        return n * factorial( n - 1 );
    }
}

integer number = 5;
integer result = factorial( number );

if (result != -1) {
    llSay(0, "Factorial of " + (string)number + " is " + (string)result );  // Factorial of 5 is 120
} else {
    llSay(0, (string)number + " is not valid" );
}

The functions use the keyword "function" and, of course, no types for the parameters or the return value.

In the viewer we see two example functions, lines 2-8 and lines 11-28.

In line 8 is how ll functions could look in LuaSL. We will have all the functions with the same parameters and the difference will be calling them with a "." between "ll" and the name of the function.

In line 13 we return "nil" instead of "-1". The value "nil" means that the variable has no value, it's empty. We use it again in line 24.

In line 25 we don't need to typecast the number to a string. It's done automatically.


Tables as lists

-- tables as lists (Lua)

fruits = { "Apple", "Banana", "Cherry", "Orange" }

for index, fruit in ipairs( fruits ) do
    print( "Fruit "..index..": "..fruit )
    -- Fruit 1: Apple
    -- Fruit 2: Banana
    -- Fruit 3: Cherry
    -- Fruit 4: Orange
end

print (#fruits)  -- 4
// tables as lists (LSL)
integer i;
list fruits = [ "Apple", "Banana", "Cherry", "Orange" ];

for ( i = 0; i < llGetListLength( fruits ); i++ ) {
    llSay(0, "Fruit " + (string)i + ": " + llList2String( fruits, i ) );
    // Fruit 1: Apple
    // Fruit 2: Banana
    // Fruit 3: Cherry
    // Fruit 4: Orange
}

llSay(0, (string)llGetListLength( fruits ) )  // 4;

The tables are the most important data structure in Lua.

In the viewer we see an example of a table used as an array, in the same way as LSL lists.

{ and } are used instead of [ and ] to initialize it.

In line 5 there is the other type of "for", the "for...in".

"ipairs" is a system function that iterates on all the values of an array table. It returns two values, stored in "index" and "fruits". We will see in a while that functions can return several values.

The arrays start from 1, not 0, as we can see in the results in lines 7-10. Also the indexes of the strings start with 1 instead of 0.

The operator #, that we have seen previously returning the length of a string, also returns the number of elements in an array table.


Tables as (key, value) pairs (like the linkset data)

-- Tables as (key, value) pairs (like the linkset data) (Lua)

fruitQuantity = {
    Apple = 50,
    Banana = 30,
    Cherry = 20,
    Orange = 15
}

for fruit, quantity in pairs(fruitQuantity) do
    print(fruit..": ".. quantity)
    -- Cherry: 20
    -- Orange: 15
    -- Banana: 30
    -- Apple: 50
end
// Tables as (key, value) pairs (like the linkset data) (LSL)
integer i;

llLinksetDataWrite( "Apple", "50" );
llLinksetDataWrite( "Banana", "30" );
llLinksetDataWrite( "Cherry", "20" );
llLinksetDataWrite( "Orange", "15" );
list fruitQuantity = llLinksetDataListKeys( 0, 0 );

for ( i=0; i < llGetListLength( fruitQuantity ); i++ ) {
    llSay(0, llList2String( fruitQuantity, i ) + ": " + llLinksetDataRead( llList2String( fruitQuantity, i ) ) );
    // Apple: 50
    // Banana: 30
    // Cherry: 20
    // Orange: 15
}

Tables can also be used as dictionaries (pairs of key-value). In the viewer we are comparing it to the linkset data, which is a different thing, but has the same data structure.

In lines 3-8 we are filling the table with pairs of keys and values.

In the "for", line 10, we use "pairs" instead of "ipairs". "ipairs" is optimized for array tables and only works with them.

We are not looking at events or states, because we don't know yet how they are implemented in LuaSL.

Luau has events, but not states. This is not a problem because Luau events are very flexible and can be used in a "states-like" way.