Nexus:TJI Scope of variables

From NexusWiki
Jump to: navigation, search

Scope of Variables

Introduction to variables

A variable is an expression in a programming language that allows you to store information. Different languages have different methods and implementations for this (some don't even have them).

In nexus, variables are weakly typed. What does that mean, you may ask yourself? Well, it means that variables can store anything. The "how" is unknown to us, it could be dynamically typed like python or just not typed at all, like smalltak where they're just pointers. But that's not what's important. What is important, though, is that one variable can store anything, like numbers, objects, lists, etc.

So a variable you were using for, let's say, store a ship object

ship := GetSceneObj("My Ship");

can be then used to store something else, like a string. (although that's a horrible style of coding)

ship := "Hello World";

If you have had experience in other languages, you'll notice than in Black Ruler you don't have to declare the variables anywhere, you just invoke them. The name of the variable can be anything and it won't matter, except for the scope of said variable.


Scope of Variables

The "scope" of a variable means from where in the script that variable can be accessed.


"e." variables

These variables are vital to any code, and you'll probrably be using them a lot, so pay attention. They mark the lowest scope of all, and can only be reached from within the block they were first invoked, and when that block's finished executing they will disappear.

Examples:

a)

rule 	event DoSomething
		:action
			e.string:="Hello World";
			Debug(e.string);
			LocalEvent(DoSomethingElse);
		:end
END

Rule	event DoSomethingElse
		:action
			debug(e.string);
		:end
END

in this case, in the debug screen it'll appear written "Hello World" and below it "0", as the two "e.string" variables are not the same.

b)

Rule 	event DoSomething
		:action
			e.string:="Hello World";
			Delay(0,1,
				Debug(e.string);
			,0);
		:end
END

What would it appear on the debug screen? The answer is "0". We don't exactly know how, but the delay command generates a new block where all the variables present in that block are independant from the block they where called from.

c)

rule 	event DoSomething
		:action
			e.string:="Hello World";
			Debug(e.string);
			LocalEvent(DoSomethingElse, e.string:="Hello again");
		:end
END

Rule	event DoSomethingElse
		:action
			debug(e.string);
		:end
END

In this case, however, the debug screen will show "Hello world" and below it "Hello again". Why? because the string "Hello again" was passed as an argument to the DoSomethingElse rule and stored in that rule's "e.string" variable.


"p." variables

Those variables access the variables stored in the previous event. This always means the directly previous valid E. variables. It's used mainly, if not always, to pass parametres from one event to an other or from an event to a delay function.

Example: a) Going back to the variables of the rule the delay function is called

Rule 	event DoSomething
		:action
			e.string:="Hello World";
			Delay(0,1,
				Debug(e.string);
			,e.string:=p.string);
		:end
END

This time in the debug screen it'll appear"Hello World", because the delay's "e.string" variable was declared with the content of the "DoSomething" rule's "e.string" variable (note that the name doesn't have to be the same, but it's good practice to keep it that way).

b)

rule 	event DoSomething
		:action
			e.string:="Hello World";
			Debug(e.string);
			LocalEvent(DoSomethingElse, e.string:=p.string);
		:end
END

Rule	event DoSomethingElse
		:action
			debug(e.string);
		:end
END

Same as above. The "DoSomethingElse" Rule's e.string variable was declared with the "DoSomething" rule "e.string"'s content. Note that ALWAYS when passing arguments with functions like "LocalEvent", "MEvent", "ChangeState", "Delay", etc, you have to use the p prefix to access the variables of the rule this functions were called from, and that p prefix is only used to access the ones with the E prefix.


variables withouth a prefix

Those variables are what we could call "semi-global". Their scope extends within the machine they were first declared, so the contents of that variable can be accessed and changed from any rule in any state of that machine, and it can, of course, be passed as an argument to an other state in an other machine (in the form of a E. variable or any other). You're probably feeling excited about this type of variables, as you don't have to deal with passing parametres and e. or p. variables and all that. Well, don't. Global or semi-global variables are a bad deal in any programming language, and you must avoid them whenever it's possible, because they can break your code if you're not cautius or at least make it unreadable by someone on the outside, as keeping track of those variables in a complex code is a pain.


"M." variables

In all sense and purpose, these are global variables. Their scope extends towards the entire mission, meaning that any rule being executed in your mission can access it and change it. Same recommendation as before: Be careful with it. My recommendation is that use them only for declaring mission "constants" (like ships) or in the worst case some very specific boolean flag, nothing more.


"S." variables

These variables only make sense inside a selection, like the Execlist or SelectEx command. They only live through one iteration of said commands, so declaring them out of the blue doesn't make a lot of sense.

What's important about them, though, is that in those selections the selected object can accessed via the "s.this" variable you all head about. And as any s. variable it will change at the end of the cicle's iteration.