Thursday, November 30, 2006

Scripting: the basics, part 2

In the first part, we wrote a couple of functions, and used another one a couple of times, but we didn't really go over what a function is, how it works, or why you would want to use one. Here we will look at functions, and also at the types of data which Second Life scripts can use.

In LSL, the Linden Scripting Language (and in programming in general), a function is a modular unit of code which can optionally be passed a number of parameters, and which can optionally return a value.

float quintuple( float theNumber )
{
return theNumber * 5.0; // Multiply by 5
}

A silly little example, but it should serve to illustrate the main points of a function.

First, we have the function declaration. This consists of three parts: the optional return type (in this case, a "float", or floating-point number — a number which can have a decimal point, as opposed to an integer which must be a whole number), the function name, and the optional parameter list, which shows what kind of data the function expects, and gives it a (hopefully) descriptive name.

If your function doesn't return a value, leave off the return type. If it does return a value, the return type must indicate the type of data the function will return (we'll cover data types later on in this post). The function name is required (otherwise there's no way to call the function). The parentheses which enclose the parameter list must be present in every function declaration, even if you have no actual parameters.

Next we have the curly brackets which enclose the statements of the function itself. Curly brackets are used to group multiple statements into a larger unit. They are required to enclose the body of a function, even if the body consists of only one statement (as this one does).

And inside the curly brackets we have a statement which multiplies the parameter by 5, and returns that value. The statement ends with a semicolon. After the semicolon are two forward slashes (//) — this starts a comment. You can put anything you want in a comment, but usually comments are used to explain what's going on (either so that somebody else reading your script can understand what your intent is, or when you come back to modify your script months later, you can understand what your intent was).

And finally we have the closing curly bracket, which terminates the function declaration.

If we were to call this function from elsewhere in the script, it might look something like this:
float result = quintuple( 3.0 );
This line creates a new floating-point variable named "result", and assigns the return value of our "quintuple" function to it. Since we pass it the number 3.0 as the parameter, and the function multiplies the parameter by 5.0, we should end up with 15.0 in the variable named result.

Why would you want to use this as a function, rather than just multiplying values directly in your code? Well, you wouldn't; as I said, this was just a silly example. But if you have a case where you perform multiple actions on some data, and you have to perform these actions many times from different places in your code, you might turn the actions into a function. You can also improve the readability of complex code by moving logical groupings of instructions into their own functions.

And now a word about variables, and the types of data they can represent.

A variable is a way of storing values for later use. You can store seven types of values in LSL:

  • integer - a whole number, with no decimal point. (examples: 0, 1, -27, 42, 2147483647)

  • float - a floating-point number, or one with a decimal point. (examples: 0.0, 3.141592654, 17.6, -57.0)

  • string - text data. String values are enclosed in quotes when you define them. (examples: "Hello, Avatar!", "yes", "no", "I'm sorry, Dave, but I'm afraid I can't do that.", "1942"1)

  • key - A special kind of string, which represents something within Second Life. Key values are also enclosed in quotes when you define them. (example: "c541c47f-e0c0-058b-ad1a-d6ae3a4584d9")

  • vector - a three-part number which represents a 3D position in space. You can also use vectors to store Euler rotations, but we won't get into those quite yet. The components of a vector are each float numbers. (examples: <0,0,0>2, <17.8,32.5,16.0>)

  • rotation - similar to a vector, only with four components. These are used for quaternion rotations, and will make your brain hurt. (examples: <0,0,0,1>, <3.141592654,0.0,0.0,1.0>)

  • list - a special kind of data type which can contain zero or more elements of any other data type. Lists are signified by square brackets surrounding their elements, which are separated by commas. We'll get into lists much later. (examples: [0,1,2,3,4,5], ["Bob", "Mary", "Joe", "Sue"], [], [1, 3.141592654, "Isn't this fun?", <0,0,0>])



1. Even though 1942 is an integer, you can have a numeric value in a string. It's the quotes that make all the difference.

2. If a float number has nothing but zeroes after the decimal point, you can usually leave off the decimal point; LSL will usually promote it to a float. Usually. This is not, however, always the case; certain functions will produce errors if you pass an integer in a list where a float is expected.

6 comments:

Anonymous said...

Do you know if it's possible to call a function in one script from another script? As i understand it now it's not?

Blueman Steele said...

Scripts in the same object and in linked objects can send messages to each other to indirectly access functions, but this likely slows down things a bit. Plus setting up the communication would be more work than just putting the function in each script.

Anonymous said...

hi Johanna,

thanks for your tutorials. I find them helpful. I have a problem creating my own functions though. I get syntax errors even if I copy/paste the quintuple function.. any ideas why?

thx!

Anonymous said...

Hello, I'm Juanmi, a Computer Student of Spain.

I am Erasmus in Milano (Italy) and i have to do a project (Tesis) about Second Life, exactly I need information about:
"Scripting & Development IN/FOR Second Life"

Maybe you have any tutorials or any information likes webs or interesants links. Please send me to mawoferty@gmail.com

THANKS FOR ALL!!!

Anonymous said...

You can get arount the float error when passimg integer values in a list to a float function arguement by placing '.f' at the end of the number. Example ["list item",22.f] will typecast the number 22 as floating instead of integer.

Johanna Hyacinth said...

Is there an advantage to typing "22.f" as opposed to "22.0"? Same number of characters, and (as far as I can tell) same result.

What we really need is a suffix to differentiate a string from a key, since I don't believe there's a way to typecast to key when initializing a global list (though it works well enough for local variables).