The Revolution scripting language, formerly called Transcript, is a full-featured programming language with all the constructs of Pascal, BASIC, C, and other common procedural programming languages. This reading will explain how Revolution implements these basic constructs. Those who have experience with programming languages will recognize the similarities and differences.
By the end of this reading you should be able to answer the following questions (all within the context of Revolution):
Variable: A variable is a named location that can hold a value. It can be visualized as a box in the computer's memory with a name on it. The box can hold some information which can be referenced by the name. A Revolution variable name:
put "stuff" into holder
If you script it like this, the last word in the put statement—holder, in this example—will become a variable, and it will hold the value of the second word of the statement—"stuff".
Think of creating a variable this way: You've seen and used a trash can. It's a holder for things. Let's create an imaginary trash can and call it "Oscar" (indulge me). If you put a newspaper into the trash can, the newspaper is still a newspaper. You can look inside the can and identify its contents as a newspaper. You can reach inside the can and pull out the newspaper and replace it with an apple core. Oscar now contains an apple core (which retains its identity as an apple core). If you place the newspaper into a different trash can called "Felix," it is still a newspaper. Throughout all this, the trash cans retain their names and you can still refer to them as Oscar or Felix (an odd couple), since the trash cans never lose their names or identities as containers though their contents may change. At the end of our example, then, Oscar is holding an apple core and Felix is holding a newspaper (so apropos).
It's the same way with a variable. If you have a variable and you name it holder for example, then you put "3" into that variable, the variable holder is just a container and inside it is the character "3." Putting 3 into the variable doesn't change the value or nature of the 3 and it doesn't change the variable's name.
The first time you state the name of a variable, the virtual box or container with that name is created. Once the variable has been created, you may use the name to put a value into the variable. You may also use the name to put the value the variable contains somewhere else. The value within a variable exists only for the handler in which it is created. As soon as the handler finishes executing its commands, the variable disappears. The next time the handler is executed, the variable is created anew and does not retain its value from the previous time the handler was executed. In the example above holder would exist as a variable (and consequently its contents) only for the duration of the handler in which it was created.
local and globalOften you may want a variable to retain its value beyond the scope of just one handler. In order for a variable and its value to persist longer than the life of the handler, it must be declared as as either a global variable or a script local variable . Once created, these types of variables and their contents persist after a handler has finished running.
Script local variables are accessible from any handler in the script where they are declared. Simply include this statement outside of all handlers in a script:
local someLocalVar
on handler1
--do some stuff
put "hello" into someLocalVar
end handler1
on handler2
--do some other stuff
put someLocalVar into field "result"
end handler2
Once declared in the script, this variable and its value are accessible from any handler in the script. In the example above the value of someLocalVar is accessible between both handler1 and handler2. Assuming handler1 runs first, handler2 will put the text "hello" into the field.
Global variables can be accessed anywhere in the stack where they are declared. Unlike a variable used only inside one handler, a global variable retains its value even after the execution of the handler that created it. Declaring a global variable is simple:
global someGlobalVar
A global variable must be declared and identified as such in every script that uses that global variable. Otherwise, the handlers that use the variable name will instead create temporary handler-only variables with the same name. For example:
global holder
on handler1
put 12 into holder
end handler1
on handler2
add 6 to holder
end handler2
When handler1 is executed, holder is given the value of 12. This value is then accessible to all handlers in that script (and in any script where global holder is declared.) Thus, after handler2 runs (again assuming that handler1 was run before it,) the value of holder becomes 18.
Contrast this to the case where no global variable is declared:
on handler1
put 12 into holder
end handler1
on handler2
add 6 to holder
end handler2
In this case, holder has a value of 12 while handler1 is running. It has a value of 6 by the end of handler2. Unless the variable is declared as global (or local) outside of the handlers the variable and its value is temporary and limited to the handler in which it is created.
It is also possible to declare local and global variables inside a handler within a particular script. This would make the variable accessible only to the handlers in which the local or global variable is declared. For example:
on handler1
global holder
put 12 into holder
end handler1
on handler2
add 6 to holder
end handler2
In this case, the global variable holder is available only to handler1 (and any other script or handler in the stack that declare holder as global.) It is not available to handler2.
Both local and global variables and and their values disappear when the stack is closed and removed from memory. So the variable and its value would not persist if you quit Revolution and restarted it, for example.
Container: A container is anything that possesses a name and can hold a certain value or string of characters. By this definition, then, a variable is also known as a container. A Revolution field has a name and can hold values and strings, and is therefore a container. In this respect a field is similar to a variable but differs in that it has a visible presence on the card, not just in memory. Consequently, values stored in fields become part of the stack and do not disappear once the application quits (if you've saved the stack). The term "container" in Revolution therefore encompasses variables and fields to refer to both. Another way to think of this is that variables and fields are subsets of the the larger group of containers.
The special variable it: This is a special-purpose variable/container to hold the results of the get command (and several other commands you'll learn about later). It also serves to make scripts more readable. However, you need to be careful as the it variable is not the same as the pronoun "it" in English.
A constant is a named container, similar to a variable. However, as the term implies, the value of a constant is fixed and cannot be changed. Constants make it fast and easy to refer to certain characters or values that are commonly used.
Text constants: Revolution defines several text constants to provide special characters that cannot readily be typed in directly.
Other constants: A number of other constants represent numeric and mathematical values, and can be used for convenience and readability:
A literal is something that is the value itself. In Revolution scripting, anything enclosed in double quotes is treated as a literal. This becomes extremely important in keeping literals distinguished from variables. A variable with nothing in it often (but not always) functions like a literal. This can cause considerable confusion. Look at this handler, for example:
on mouseUp show image flower end mouseUp
Revolution, attempting to be helpful, will try to figure out what the word 'flower' is. Since you have never used it as a variable, Revolution will assume you meant it to be a literal value, and show the image object named "flower", if any. This might be alright and never cause a problem. But what if your handler became much longer, and the show image statement was joined by many others? Then, months later, you come back and decide you need a variable at the top of your handler for some other reason. You decide that 'flower' makes a good variable name so you do this:
on mouseUp put "petunia" into flower -- in the meantime, you have placed -- lots more commands here, and you forgot -- that you had this statement: show image flower end mouseUp
Now, suddenly, your handler that was reliably showing an image named "flower" is suddenly showing an image named "petunia", or more likely, producing an error because there isn't any image named "petunia"! It is a good practice to always use quotes around the names of all objects when referring to them by their names, to avoid problems like this one.
Let's consider the opposite situation, where you put quote marks where you don't intend them. Look at this handler:
on mouseUp put "flower" into thisImage show image thisImage end mouseUp
This would take the literal string "flower" and place it within a variable called "thisImage." In referencing the variable on the very next line, the handler actually looks at the contents of the variable. Therefore, the handler would display an image called "flower." However, the handler would operate differently if one line were changed minutely:
on mouseUp put "flower" into thisImage show image "thisImage" end mouseUp
Here the second command of the handler would try to display an image called "thisImage" since enclosing thisImage within quotation marks indicates that it is to be treated as a literal and not as a variable. Details matter!
Operator: An operator specifies an operation to be performed on its operands. You are probably most familiar with arithmetic operators:
Transcript follows the standard order of precedence in arithmetic operators you learned in algebra:
As in algebra, parentheses can be used to override default precedence.
Some operators are keywords rather than symbols:
put 25 div 8 into myNumber
This divides 25 by 8 and puts the result of 3 into the variable myNumber. The remainder of 1 is ignored and lost in the digital ether.
put 25 mod 8 into myNumber
This divides 25 by 8 and puts the remainder of 1 into the variable myNumber. The rest of the answer is ignored and lost in the digital ether.
We will see other operators later.
Put:The put command is used to put values into containers. You accomplished this when you put various strings into a field. As shown above it works essentially the same for variables. In this regard it is designated as Revolution's assignment statement. The following key words determine how the new value affects the existing contents of the container:
on mouseUp put "Eeyore" into hundredAcreWood put "Pooh Bear" into hundredAcreWoodend mouseUp
This handler will take the literal string "Eeyore" and place it into the variable hundredAcreWood. Then it will place the another literal string "Pooh Bear" into the same variable, replacing the previous contents completely ("Typical," as Eeyore would grumble).
on mouseUp put "Eeyore" into hundredAcreWood put "Pooh Bear" after hundredAcreWood end mouseUp
This handler will place the literal string "Pooh Bear" directly after the string already residing within the variable, resulting in "EeyorePooh Bear" contained within hundredAcreWood (when genetic cloning turns awry).
on mouseUp put "Eeyore" into hundredAcreWood put "Pooh Bear" before hundredAcreWood end mouseUp
This handler will place the literal string "Pooh Bear" directly before the string already residing within the variable, resulting in "Pooh BearEeyore" contained within hundredAcreWood (more threatening than a heffalump or woozle).
Arithmetic Commands: Transcript provides four commands for common arithmetic calculations:
These commands perform the calculation on the value within the container and replace the value with the answer. Most programming languages do not have arithmetic commands like these, but accomplish the same result with an assignment statement that references the variable in the calculation and assigns the result to the same variable. This technique also works in Transcript.
A function performs a prescribed process and returns a value. Functions are used within the context of a command and may be used anywhere the value it returns is appropriate.
Forms: Revolution functions generally have two forms:
Argument: An argument is an input value for the function to work on. Most (but not all) functions require one or more arguments. With the example given above (sqrt(25)), the argument would be 25. Arguments may be specified explicitly (as above) but can also come from a variable or a field or other source of value. For example, to find the absolute value of a number using the abs() function:
on mouseUp global myNum put abs(myNum) into field "Result" end mouseUp
In this example, the argument passed to the function (in this case the absolute value) is a variable. The function will perform its operations on the contents of the variable and place the result in a certain field. Obviously, the arguments passed to a function can vary and the values the function returns are dependent upon the arguments passed.
Commonly-used Functions
random: This is a function that can often be used in instructional applications to provide variety and unpredictability. It returns a random value between 1 and the argument, inclusive. For example:
on mouseUp put random(20) end mouseUpThis handler would then put into the message box any number between 1 and 20, the lowest possible value being 1, and the highest possible value being 20.
round: Rounds a number up or down according to standard rounding rules.
put the round of 36.4 -- yields 36 put round(36.446,2) -- rounds to two decimal places; yields 36.45date: Returns the current date as set by the operating system.
put the date
put date()time: returns the current time as set by the operating system.
put the time put time()
We will see many more functions later. You are welcome to explore and experiment with some of them. They are always identified as functions in the Revolution Language Dictionary.
This is the operation of appending text together, "adding" (disregarding the arithmetic implications of the word) one chunk of text to another. The ampersand (&) is the primary concatenation operator/symbol in Revolution.
put "This" & "is" & "my" & "stack" into myStack
This results in a string "Thisismystack" being placed in the variable myStack.
put "This" && "is" && "my" && "stack" into myStack
This results in a string "This is my stack" being placed in the variable myStack.
The comma (,) is a special concatenation symbol in Transcript. For example:
on mouseUp
put "Eeyore","Pooh Bear" into hundredAcreWood
end mouseUp
This handler would place the two strings together with a comma separating them (resulting in Eeyore,Pooh Bear) into a variable. This symbol is an effective tool for concatenating several strings into a single comma-delimited string.