<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.flightgear.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vin</id>
	<title>FlightGear wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.flightgear.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vin"/>
	<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/Special:Contributions/Vin"/>
	<updated>2026-04-04T12:02:07Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Multiplayer_protocol&amp;diff=78337</id>
		<title>Multiplayer protocol</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Multiplayer_protocol&amp;diff=78337"/>
		<updated>2014-12-17T06:36:04Z</updated>

		<summary type="html">&lt;p&gt;Vin: Rearrange order&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Resources ==&lt;br /&gt;
&lt;br /&gt;
The routines for handling XDR are contained in $FG_SRC/Multiplayer/tiny_xdr.[h|c]xx:&lt;br /&gt;
&lt;br /&gt;
http://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/tiny_xdr.cxx&lt;br /&gt;
&lt;br /&gt;
The different message types supported by the MP protocol are specified in $FG_SRC/MultiPlayer/mpmessages.hxx:&lt;br /&gt;
&lt;br /&gt;
http://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/mpmessages.hxx&lt;br /&gt;
&lt;br /&gt;
The multiplayer system code:&lt;br /&gt;
&lt;br /&gt;
https://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/multiplaymgr.cxx&lt;br /&gt;
&lt;br /&gt;
eXternal Data Representation (XDR):&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/External_Data_Representation&lt;br /&gt;
&lt;br /&gt;
Multiplayer Forum Post (very helpful):&lt;br /&gt;
&lt;br /&gt;
http://forum.flightgear.org/viewtopic.php?f=18&amp;amp;t=13510&amp;amp;hilit=development+help+xdr#p136501&lt;br /&gt;
&lt;br /&gt;
== The messages ==&lt;br /&gt;
&lt;br /&gt;
All messages are composed of XDR encoded data. (see [http://www.faqs.org/rfcs/rfc1832.html RFC 1832] for a complete description of XDR). XDR basically means: All data is in network byte order and aligned to the nearest multiple of 4 bytes. Strings are encoded as a zero-terminated array of characters,aligned to the nearest multiple of 4 bytes. Floating point numbers (32 or 64 bit) must be encode in the IEEE standard.&lt;br /&gt;
FlightGear uses XDR encoded messages that are sent via UDP.&lt;br /&gt;
&lt;br /&gt;
== The header ==&lt;br /&gt;
The header is always 32 bytes long and contains the following fields in exactly that order:&lt;br /&gt;
&lt;br /&gt;
 |'''Magic'''|'''Version'''|'''MsgId'''|'''MsgLen'''|'''ReplyAddress'''|'''ReplyPort'''|'''Callsign'''|'''Data'''|&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Magic:&lt;br /&gt;
|4 bytes, always 0x46474653 (&amp;quot;FGFS&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
|Version:&lt;br /&gt;
|4 bytes, protocol version, currently 0x00010001 (1.1)&lt;br /&gt;
|-&lt;br /&gt;
|MsgId:&lt;br /&gt;
|4 bytes, defines what data is appended to the header. Can be 0x00000001 for chat messages (deprecated) or&amp;lt;br /&amp;gt;&lt;br /&gt;
0x00000007 for position data - all other values are outdated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|MsgLen:&lt;br /&gt;
|4 bytes, the length of the data. {{Caution|This is not in bytes, see the description of STRING field at the end for more information.}}&lt;br /&gt;
|-&lt;br /&gt;
|ReplyAddress:&lt;br /&gt;
|4 bytes, deprecated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|ReplyPort:&lt;br /&gt;
|4 bytes, deprecated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|Callsign:&lt;br /&gt;
|8 bytes, zero terminated array of characters representing&lt;br /&gt;
the user callsign&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Data of chat messages ==&lt;br /&gt;
The data for chat messages is a zero terminated array of characters. The MsgLen field in the header represents its length. The maximum length is defined to be 256 bytes.&lt;br /&gt;
&lt;br /&gt;
== Data of position messages ==&lt;br /&gt;
The data of position data is more complicated and looks like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|ModelName&lt;br /&gt;
|96 bytes, zero terminated array of characters representing the aircraft model used by the user&lt;br /&gt;
|-&lt;br /&gt;
|time&lt;br /&gt;
|8 bytes, representing the time when this message was generated double&lt;br /&gt;
|-&lt;br /&gt;
|lag  || 8 bytes, time offset for network lag double&lt;br /&gt;
|-&lt;br /&gt;
|PosX || 8 bytes, XDR encoded double value, X-ccordinate of users&amp;lt;br /&amp;gt;&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|PosY || 8 bytes, XDR encoded double value, Y-ccordinate of users&amp;lt;br /&amp;gt;&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|PosZ || 8 bytes, XDR encoded double value, z-ccordinate of users&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|OriX || 4 bytes, XDR encoded float value, X-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|OriY || 4 bytes, XDR encoded float value, Y-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|OriZ || 4 bytes, XDR encoded float value, Z-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|VelX || 4 bytes, XDR encoded float value, velocity of the user in X direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|VelY || 4 bytes, XDR encoded float value, velocity of the user in Y direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|VelZ || 4 bytes, XDR encoded float value, velocity of the user in Z direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|pad || up to 8 bytes for padding the data to a multiple of 8 bytes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is followed by '''property-values''', which are encoded in the form '''ID'''|'''Value'''&lt;br /&gt;
&lt;br /&gt;
{{Note|This table is is current for FlightGear 3.2.0.  For the list in the development version, see {{Git link|gitorious|fg/flightgear|master|src/MultiPlayer/multiplaymgr.cxx|text=src/MultiPlayer/multiplaymgr.cxx}}.}}&lt;br /&gt;
&lt;br /&gt;
The following properties are transmitted, but not necessarily all present and not in this order:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID  !!  Property                                              || [[#Types|Types]]&lt;br /&gt;
|-&lt;br /&gt;
|100 || surface-positions/left-aileron-pos-norm                || float&lt;br /&gt;
|-&lt;br /&gt;
|101 || surface-positions/right-aileron-pos-norm               || float&lt;br /&gt;
|-&lt;br /&gt;
|102 || surface-positions/elevator-pos-norm                    || float&lt;br /&gt;
|-&lt;br /&gt;
|103 || surface-positions/rudder-pos-norm                      || float&lt;br /&gt;
|-&lt;br /&gt;
|104 || surface-positions/flap-pos-norm                        || float&lt;br /&gt;
|-&lt;br /&gt;
|105 || surface-positions/speedbrake-pos-norm                  || float&lt;br /&gt;
|-&lt;br /&gt;
|106 || gear/tailhook/position-norm                            || float&lt;br /&gt;
|-&lt;br /&gt;
|107 || gear/launchbar/position-norm                           || float&lt;br /&gt;
|-&lt;br /&gt;
|108 || gear/launchbar/state                                   || string&lt;br /&gt;
|-&lt;br /&gt;
|109 || gear/launchbar/holdback-position-norm                  || float&lt;br /&gt;
|-&lt;br /&gt;
|110 || canopy/position-norm                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|111 || surface-positions/wing-pos-norm                        || float&lt;br /&gt;
|-&lt;br /&gt;
|112 || surface-positions/wing-fold-pos-norm                   || float&lt;br /&gt;
|-&lt;br /&gt;
|200 || gear/gear[0]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|201 || gear/gear[0]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|210 || gear/gear[1]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|211 || gear/gear[1]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|220 || gear/gear[2]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|221 || gear/gear[2]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|230 || gear/gear[3]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|231 || gear/gear[3]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|240 || gear/gear[4]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|241 || gear/gear[4]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|300 || engines/engine[0]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|301 || engines/engine[0]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|302 || engines/engine[0]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|310 || engines/engine[1]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|311 || engines/engine[1]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|312 || engines/engine[1]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|320 || engines/engine[2]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|321 || engines/engine[2]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|322 || engines/engine[2]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|330 || engines/engine[3]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|331 || engines/engine[3]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|332 || engines/engine[3]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|340 || engines/engine[4]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|341 || engines/engine[4]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|342 || engines/engine[4]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|350 || engines/engine[5]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|351 || engines/engine[5]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|352 || engines/engine[5]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|360 || engines/engine[6]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|361 || engines/engine[6]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|362 || engines/engine[6]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|370 || engines/engine[7]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|371 || engines/engine[7]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|372 || engines/engine[7]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|380 || engines/engine[8]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|381 || engines/engine[8]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|382 || engines/engine[8]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|390 || engines/engine[9]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|391 || engines/engine[9]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|392 || engines/engine[9]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|800 || rotors/main/rpm                                        || float&lt;br /&gt;
|-&lt;br /&gt;
|801 || rotors/tail/rpm                                        || float&lt;br /&gt;
|-&lt;br /&gt;
|810 || rotors/main/blade[0]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|811 || rotors/main/blade[1]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|812 || rotors/main/blade[2]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|813 || rotors/main/blade[3]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|820 || rotors/main/blade[0]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|821 || rotors/main/blade[1]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|822 || rotors/main/blade[2]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|823 || rotors/main/blade[3]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|830 || rotors/tail/blade[0]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|831 || rotors/tail/blade[1]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|900 || sim/hitches/aerotow/tow/length                         || float&lt;br /&gt;
|-&lt;br /&gt;
|901 || sim/hitches/aerotow/tow/elastic-constant               || float&lt;br /&gt;
|-&lt;br /&gt;
|902 || sim/hitches/aerotow/tow/weight-per-m-kg-m              || float&lt;br /&gt;
|-&lt;br /&gt;
|903 || sim/hitches/aerotow/tow/dist                           || float&lt;br /&gt;
|-&lt;br /&gt;
|904 || sim/hitches/aerotow/tow/connected-to-property-node     || bool&lt;br /&gt;
|-&lt;br /&gt;
|905 || sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign || string&lt;br /&gt;
|-&lt;br /&gt;
|906 || sim/hitches/aerotow/tow/brake-force                    || float&lt;br /&gt;
|-&lt;br /&gt;
|907 || sim/hitches/aerotow/tow/end-force-x                    || float&lt;br /&gt;
|-&lt;br /&gt;
|908 || sim/hitches/aerotow/tow/end-force-y                    || float&lt;br /&gt;
|-&lt;br /&gt;
|909 || sim/hitches/aerotow/tow/end-force-z                    || float&lt;br /&gt;
|-&lt;br /&gt;
|930 || sim/hitches/aerotow/is-slave                           || bool&lt;br /&gt;
|-&lt;br /&gt;
|931 || sim/hitches/aerotow/speed-in-tow-direction             || float&lt;br /&gt;
|-&lt;br /&gt;
|932 || sim/hitches/aerotow/open                               || bool&lt;br /&gt;
|-&lt;br /&gt;
|933 || sim/hitches/aerotow/local-pos-x                        || float&lt;br /&gt;
|-&lt;br /&gt;
|934 || sim/hitches/aerotow/local-pos-y                        || float&lt;br /&gt;
|-&lt;br /&gt;
|935 || sim/hitches/aerotow/local-pos-z                        || float&lt;br /&gt;
|-&lt;br /&gt;
|1001 || controls/flight/slats                                 || float&lt;br /&gt;
|-&lt;br /&gt;
|1002 || controls/flight/speedbrake                            || float&lt;br /&gt;
|-&lt;br /&gt;
|1003 || controls/flight/spoilers                              || float&lt;br /&gt;
|-&lt;br /&gt;
|1004 || controls/gear/gear-down                               || float&lt;br /&gt;
|-&lt;br /&gt;
|1005 || controls/lighting/nav-lights                          || float&lt;br /&gt;
|-&lt;br /&gt;
|1006 || controls/armament/station[0]/jettison-all             || bool&lt;br /&gt;
|-&lt;br /&gt;
|1100 || sim/model/variant                                     || int&lt;br /&gt;
|-&lt;br /&gt;
|1101 || sim/model/livery/file                                 || string&lt;br /&gt;
|-&lt;br /&gt;
|1200 || environment/wildfire/data                             || string&lt;br /&gt;
|-&lt;br /&gt;
|1201 || environment/contrail                                  || int&lt;br /&gt;
|-&lt;br /&gt;
|1300 || tanker                                                || int&lt;br /&gt;
|-&lt;br /&gt;
|1400 || scenery/events                                        || string&lt;br /&gt;
|-&lt;br /&gt;
|1500 || instrumentation/transponder/transmitted-id            || int&lt;br /&gt;
|-&lt;br /&gt;
|1501 || instrumentation/transponder/altitude                  || int&lt;br /&gt;
|-&lt;br /&gt;
|1502 || instrumentation/transponder/ident                     || bool&lt;br /&gt;
|-&lt;br /&gt;
|1503 || instrumentation/transponder/inputs/mode               || int&lt;br /&gt;
|-&lt;br /&gt;
|10001 || sim/multiplay/transmission-freq-hz                   || string&lt;br /&gt;
|-&lt;br /&gt;
|10002 || sim/multiplay/chat                                   || string&lt;br /&gt;
|-&lt;br /&gt;
|10100 || sim/multiplay/generic/string[0]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10101 || sim/multiplay/generic/string[1]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10102 || sim/multiplay/generic/string[2]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10103 || sim/multiplay/generic/string[3]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10104 || sim/multiplay/generic/string[4]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10105 || sim/multiplay/generic/string[5]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10106 || sim/multiplay/generic/string[6]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10107 || sim/multiplay/generic/string[7]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10108 || sim/multiplay/generic/string[8]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10109 || sim/multiplay/generic/string[9]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10110 || sim/multiplay/generic/string[10]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10111 || sim/multiplay/generic/string[11]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10112 || sim/multiplay/generic/string[12]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10113 || sim/multiplay/generic/string[13]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10114 || sim/multiplay/generic/string[14]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10115 || sim/multiplay/generic/string[15]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10116 || sim/multiplay/generic/string[16]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10117 || sim/multiplay/generic/string[17]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10118 || sim/multiplay/generic/string[18]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10119 || sim/multiplay/generic/string[19]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10200 || sim/multiplay/generic/float[0]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10201 || sim/multiplay/generic/float[1]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10202 || sim/multiplay/generic/float[2]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10203 || sim/multiplay/generic/float[3]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10204 || sim/multiplay/generic/float[4]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10205 || sim/multiplay/generic/float[5]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10206 || sim/multiplay/generic/float[6]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10207 || sim/multiplay/generic/float[7]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10208 || sim/multiplay/generic/float[8]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10209 || sim/multiplay/generic/float[9]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10210 || sim/multiplay/generic/float[10]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10211 || sim/multiplay/generic/float[11]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10212 || sim/multiplay/generic/float[12]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10213 || sim/multiplay/generic/float[13]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10214 || sim/multiplay/generic/float[14]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10215 || sim/multiplay/generic/float[15]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10216 || sim/multiplay/generic/float[16]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10217 || sim/multiplay/generic/float[17]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10218 || sim/multiplay/generic/float[18]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10219 || sim/multiplay/generic/float[19]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10300 || sim/multiplay/generic/int[0]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10301 || sim/multiplay/generic/int[1]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10302 || sim/multiplay/generic/int[2]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10303 || sim/multiplay/generic/int[3]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10304 || sim/multiplay/generic/int[4]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10305 || sim/multiplay/generic/int[5]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10306 || sim/multiplay/generic/int[6]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10307 || sim/multiplay/generic/int[7]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10308 || sim/multiplay/generic/int[8]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10309 || sim/multiplay/generic/int[9]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10310 || sim/multiplay/generic/int[10]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10311 || sim/multiplay/generic/int[11]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10312 || sim/multiplay/generic/int[12]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10313 || sim/multiplay/generic/int[13]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10314 || sim/multiplay/generic/int[14]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10315 || sim/multiplay/generic/int[15]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10316 || sim/multiplay/generic/int[16]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10317 || sim/multiplay/generic/int[17]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10318 || sim/multiplay/generic/int[18]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10319 || sim/multiplay/generic/int[19]                        || int&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Types ==&lt;br /&gt;
The types are XDR encoded as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;INT&amp;lt;/tt&amp;gt;:    4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;FLOAT&amp;lt;/tt&amp;gt;: 4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;BOOL&amp;lt;/tt&amp;gt;:  4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;STRING [LEN|STR|PAD]&amp;lt;/tt&amp;gt;:&lt;br /&gt;
** &amp;lt;tt&amp;gt;LEN&amp;lt;/tt&amp;gt;:    4 bytes, length of the decoded string&lt;br /&gt;
** &amp;lt;tt&amp;gt;STR&amp;lt;/tt&amp;gt;:    LEN*4 bytes, encoded string.&lt;br /&gt;
** &amp;lt;tt&amp;gt;PAD&amp;lt;/tt&amp;gt;:    n*4 bytes, padding.&lt;br /&gt;
{{Caution|Due to a bug, all bytes in the &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; field are sent as 4-byte ints (not in the header or the position message). So STR has length LEN*4 and padding (4-LEN%4)*4 bytes, if LEN%4 is not 0.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Multiplayer]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Multiplayer_protocol&amp;diff=78334</id>
		<title>Multiplayer protocol</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Multiplayer_protocol&amp;diff=78334"/>
		<updated>2014-12-17T02:03:39Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Resources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== The messages ==&lt;br /&gt;
&lt;br /&gt;
All messages are composed of XDR encoded data. (see [http://www.faqs.org/rfcs/rfc1832.html RFC 1832] for a complete description of XDR). XDR basically means: All data is in network byte order and aligned to the nearest multiple of 4 bytes. Strings are encoded as a zero-terminated array of characters,aligned to the nearest multiple of 4 bytes. Floating point numbers (32 or 64 bit) must be encode in the IEEE standard.&lt;br /&gt;
FlightGear uses XDR encoded messages that are sent via UDP.&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
&lt;br /&gt;
The routines for handling XDR are contained in $FG_SRC/Multiplayer/tiny_xdr.[h|c]xx:&lt;br /&gt;
&lt;br /&gt;
http://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/tiny_xdr.cxx&lt;br /&gt;
&lt;br /&gt;
The different message types supported by the MP protocol are specified in $FG_SRC/MultiPlayer/mpmessages.hxx:&lt;br /&gt;
&lt;br /&gt;
http://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/mpmessages.hxx&lt;br /&gt;
&lt;br /&gt;
The multiplayer system code:&lt;br /&gt;
&lt;br /&gt;
https://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/multiplaymgr.cxx&lt;br /&gt;
&lt;br /&gt;
eXternal Data Representation (XDR):&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/External_Data_Representation&lt;br /&gt;
&lt;br /&gt;
Multiplayer Forum Post (very helpful):&lt;br /&gt;
&lt;br /&gt;
http://forum.flightgear.org/viewtopic.php?f=18&amp;amp;t=13510&amp;amp;hilit=development+help+xdr#p136501&lt;br /&gt;
&lt;br /&gt;
== The header ==&lt;br /&gt;
The header is always 32 bytes long and contains the following fields in exactly that order:&lt;br /&gt;
&lt;br /&gt;
 |'''Magic'''|'''Version'''|'''MsgId'''|'''MsgLen'''|'''ReplyAddress'''|'''ReplyPort'''|'''Callsign'''|'''Data'''|&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Magic:&lt;br /&gt;
|4 bytes, always 0x46474653 (&amp;quot;FGFS&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
|Version:&lt;br /&gt;
|4 bytes, protocol version, currently 0x00010001 (1.1)&lt;br /&gt;
|-&lt;br /&gt;
|MsgId:&lt;br /&gt;
|4 bytes, defines what data is appended to the header. Can be 0x00000001 for chat messages (deprecated) or&amp;lt;br /&amp;gt;&lt;br /&gt;
0x00000007 for position data - all other values are outdated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|MsgLen:&lt;br /&gt;
|4 bytes, the length of the data. {{Caution|This is not in bytes, see the description of STRING field at the end for more information.}}&lt;br /&gt;
|-&lt;br /&gt;
|ReplyAddress:&lt;br /&gt;
|4 bytes, deprecated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|ReplyPort:&lt;br /&gt;
|4 bytes, deprecated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|Callsign:&lt;br /&gt;
|8 bytes, zero terminated array of characters representing&lt;br /&gt;
the user callsign&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Data of chat messages ==&lt;br /&gt;
The data for chat messages is a zero terminated array of characters. The MsgLen field in the header represents its length. The maximum length is defined to be 256 bytes.&lt;br /&gt;
&lt;br /&gt;
== Data of position messages ==&lt;br /&gt;
The data of position data is more complicated and looks like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|ModelName&lt;br /&gt;
|96 bytes, zero terminated array of characters representing the aircraft model used by the user&lt;br /&gt;
|-&lt;br /&gt;
|time&lt;br /&gt;
|8 bytes, representing the time when this message was generated double&lt;br /&gt;
|-&lt;br /&gt;
|lag  || 8 bytes, time offset for network lag double&lt;br /&gt;
|-&lt;br /&gt;
|PosX || 8 bytes, XDR encoded double value, X-ccordinate of users&amp;lt;br /&amp;gt;&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|PosY || 8 bytes, XDR encoded double value, Y-ccordinate of users&amp;lt;br /&amp;gt;&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|PosZ || 8 bytes, XDR encoded double value, z-ccordinate of users&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|OriX || 4 bytes, XDR encoded float value, X-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|OriY || 4 bytes, XDR encoded float value, Y-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|OriZ || 4 bytes, XDR encoded float value, Z-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|VelX || 4 bytes, XDR encoded float value, velocity of the user in X direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|VelY || 4 bytes, XDR encoded float value, velocity of the user in Y direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|VelZ || 4 bytes, XDR encoded float value, velocity of the user in Z direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|pad || up to 8 bytes for padding the data to a multiple of 8 bytes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is followed by '''property-values''', which are encoded in the form '''ID'''|'''Value'''&lt;br /&gt;
&lt;br /&gt;
{{Note|This table is is current for FlightGear 3.2.0.  For the list in the development version, see {{Git link|gitorious|fg/flightgear|master|src/MultiPlayer/multiplaymgr.cxx|text=src/MultiPlayer/multiplaymgr.cxx}}.}}&lt;br /&gt;
&lt;br /&gt;
The following properties are transmitted, but not necessarily all present and not in this order:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID  !!  Property                                              || [[#Types|Types]]&lt;br /&gt;
|-&lt;br /&gt;
|100 || surface-positions/left-aileron-pos-norm                || float&lt;br /&gt;
|-&lt;br /&gt;
|101 || surface-positions/right-aileron-pos-norm               || float&lt;br /&gt;
|-&lt;br /&gt;
|102 || surface-positions/elevator-pos-norm                    || float&lt;br /&gt;
|-&lt;br /&gt;
|103 || surface-positions/rudder-pos-norm                      || float&lt;br /&gt;
|-&lt;br /&gt;
|104 || surface-positions/flap-pos-norm                        || float&lt;br /&gt;
|-&lt;br /&gt;
|105 || surface-positions/speedbrake-pos-norm                  || float&lt;br /&gt;
|-&lt;br /&gt;
|106 || gear/tailhook/position-norm                            || float&lt;br /&gt;
|-&lt;br /&gt;
|107 || gear/launchbar/position-norm                           || float&lt;br /&gt;
|-&lt;br /&gt;
|108 || gear/launchbar/state                                   || string&lt;br /&gt;
|-&lt;br /&gt;
|109 || gear/launchbar/holdback-position-norm                  || float&lt;br /&gt;
|-&lt;br /&gt;
|110 || canopy/position-norm                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|111 || surface-positions/wing-pos-norm                        || float&lt;br /&gt;
|-&lt;br /&gt;
|112 || surface-positions/wing-fold-pos-norm                   || float&lt;br /&gt;
|-&lt;br /&gt;
|200 || gear/gear[0]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|201 || gear/gear[0]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|210 || gear/gear[1]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|211 || gear/gear[1]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|220 || gear/gear[2]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|221 || gear/gear[2]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|230 || gear/gear[3]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|231 || gear/gear[3]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|240 || gear/gear[4]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|241 || gear/gear[4]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|300 || engines/engine[0]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|301 || engines/engine[0]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|302 || engines/engine[0]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|310 || engines/engine[1]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|311 || engines/engine[1]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|312 || engines/engine[1]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|320 || engines/engine[2]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|321 || engines/engine[2]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|322 || engines/engine[2]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|330 || engines/engine[3]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|331 || engines/engine[3]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|332 || engines/engine[3]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|340 || engines/engine[4]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|341 || engines/engine[4]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|342 || engines/engine[4]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|350 || engines/engine[5]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|351 || engines/engine[5]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|352 || engines/engine[5]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|360 || engines/engine[6]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|361 || engines/engine[6]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|362 || engines/engine[6]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|370 || engines/engine[7]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|371 || engines/engine[7]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|372 || engines/engine[7]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|380 || engines/engine[8]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|381 || engines/engine[8]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|382 || engines/engine[8]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|390 || engines/engine[9]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|391 || engines/engine[9]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|392 || engines/engine[9]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|800 || rotors/main/rpm                                        || float&lt;br /&gt;
|-&lt;br /&gt;
|801 || rotors/tail/rpm                                        || float&lt;br /&gt;
|-&lt;br /&gt;
|810 || rotors/main/blade[0]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|811 || rotors/main/blade[1]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|812 || rotors/main/blade[2]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|813 || rotors/main/blade[3]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|820 || rotors/main/blade[0]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|821 || rotors/main/blade[1]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|822 || rotors/main/blade[2]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|823 || rotors/main/blade[3]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|830 || rotors/tail/blade[0]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|831 || rotors/tail/blade[1]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|900 || sim/hitches/aerotow/tow/length                         || float&lt;br /&gt;
|-&lt;br /&gt;
|901 || sim/hitches/aerotow/tow/elastic-constant               || float&lt;br /&gt;
|-&lt;br /&gt;
|902 || sim/hitches/aerotow/tow/weight-per-m-kg-m              || float&lt;br /&gt;
|-&lt;br /&gt;
|903 || sim/hitches/aerotow/tow/dist                           || float&lt;br /&gt;
|-&lt;br /&gt;
|904 || sim/hitches/aerotow/tow/connected-to-property-node     || bool&lt;br /&gt;
|-&lt;br /&gt;
|905 || sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign || string&lt;br /&gt;
|-&lt;br /&gt;
|906 || sim/hitches/aerotow/tow/brake-force                    || float&lt;br /&gt;
|-&lt;br /&gt;
|907 || sim/hitches/aerotow/tow/end-force-x                    || float&lt;br /&gt;
|-&lt;br /&gt;
|908 || sim/hitches/aerotow/tow/end-force-y                    || float&lt;br /&gt;
|-&lt;br /&gt;
|909 || sim/hitches/aerotow/tow/end-force-z                    || float&lt;br /&gt;
|-&lt;br /&gt;
|930 || sim/hitches/aerotow/is-slave                           || bool&lt;br /&gt;
|-&lt;br /&gt;
|931 || sim/hitches/aerotow/speed-in-tow-direction             || float&lt;br /&gt;
|-&lt;br /&gt;
|932 || sim/hitches/aerotow/open                               || bool&lt;br /&gt;
|-&lt;br /&gt;
|933 || sim/hitches/aerotow/local-pos-x                        || float&lt;br /&gt;
|-&lt;br /&gt;
|934 || sim/hitches/aerotow/local-pos-y                        || float&lt;br /&gt;
|-&lt;br /&gt;
|935 || sim/hitches/aerotow/local-pos-z                        || float&lt;br /&gt;
|-&lt;br /&gt;
|1001 || controls/flight/slats                                 || float&lt;br /&gt;
|-&lt;br /&gt;
|1002 || controls/flight/speedbrake                            || float&lt;br /&gt;
|-&lt;br /&gt;
|1003 || controls/flight/spoilers                              || float&lt;br /&gt;
|-&lt;br /&gt;
|1004 || controls/gear/gear-down                               || float&lt;br /&gt;
|-&lt;br /&gt;
|1005 || controls/lighting/nav-lights                          || float&lt;br /&gt;
|-&lt;br /&gt;
|1006 || controls/armament/station[0]/jettison-all             || bool&lt;br /&gt;
|-&lt;br /&gt;
|1100 || sim/model/variant                                     || int&lt;br /&gt;
|-&lt;br /&gt;
|1101 || sim/model/livery/file                                 || string&lt;br /&gt;
|-&lt;br /&gt;
|1200 || environment/wildfire/data                             || string&lt;br /&gt;
|-&lt;br /&gt;
|1201 || environment/contrail                                  || int&lt;br /&gt;
|-&lt;br /&gt;
|1300 || tanker                                                || int&lt;br /&gt;
|-&lt;br /&gt;
|1400 || scenery/events                                        || string&lt;br /&gt;
|-&lt;br /&gt;
|1500 || instrumentation/transponder/transmitted-id            || int&lt;br /&gt;
|-&lt;br /&gt;
|1501 || instrumentation/transponder/altitude                  || int&lt;br /&gt;
|-&lt;br /&gt;
|1502 || instrumentation/transponder/ident                     || bool&lt;br /&gt;
|-&lt;br /&gt;
|1503 || instrumentation/transponder/inputs/mode               || int&lt;br /&gt;
|-&lt;br /&gt;
|10001 || sim/multiplay/transmission-freq-hz                   || string&lt;br /&gt;
|-&lt;br /&gt;
|10002 || sim/multiplay/chat                                   || string&lt;br /&gt;
|-&lt;br /&gt;
|10100 || sim/multiplay/generic/string[0]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10101 || sim/multiplay/generic/string[1]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10102 || sim/multiplay/generic/string[2]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10103 || sim/multiplay/generic/string[3]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10104 || sim/multiplay/generic/string[4]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10105 || sim/multiplay/generic/string[5]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10106 || sim/multiplay/generic/string[6]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10107 || sim/multiplay/generic/string[7]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10108 || sim/multiplay/generic/string[8]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10109 || sim/multiplay/generic/string[9]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10110 || sim/multiplay/generic/string[10]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10111 || sim/multiplay/generic/string[11]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10112 || sim/multiplay/generic/string[12]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10113 || sim/multiplay/generic/string[13]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10114 || sim/multiplay/generic/string[14]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10115 || sim/multiplay/generic/string[15]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10116 || sim/multiplay/generic/string[16]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10117 || sim/multiplay/generic/string[17]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10118 || sim/multiplay/generic/string[18]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10119 || sim/multiplay/generic/string[19]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10200 || sim/multiplay/generic/float[0]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10201 || sim/multiplay/generic/float[1]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10202 || sim/multiplay/generic/float[2]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10203 || sim/multiplay/generic/float[3]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10204 || sim/multiplay/generic/float[4]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10205 || sim/multiplay/generic/float[5]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10206 || sim/multiplay/generic/float[6]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10207 || sim/multiplay/generic/float[7]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10208 || sim/multiplay/generic/float[8]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10209 || sim/multiplay/generic/float[9]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10210 || sim/multiplay/generic/float[10]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10211 || sim/multiplay/generic/float[11]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10212 || sim/multiplay/generic/float[12]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10213 || sim/multiplay/generic/float[13]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10214 || sim/multiplay/generic/float[14]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10215 || sim/multiplay/generic/float[15]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10216 || sim/multiplay/generic/float[16]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10217 || sim/multiplay/generic/float[17]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10218 || sim/multiplay/generic/float[18]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10219 || sim/multiplay/generic/float[19]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10300 || sim/multiplay/generic/int[0]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10301 || sim/multiplay/generic/int[1]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10302 || sim/multiplay/generic/int[2]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10303 || sim/multiplay/generic/int[3]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10304 || sim/multiplay/generic/int[4]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10305 || sim/multiplay/generic/int[5]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10306 || sim/multiplay/generic/int[6]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10307 || sim/multiplay/generic/int[7]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10308 || sim/multiplay/generic/int[8]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10309 || sim/multiplay/generic/int[9]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10310 || sim/multiplay/generic/int[10]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10311 || sim/multiplay/generic/int[11]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10312 || sim/multiplay/generic/int[12]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10313 || sim/multiplay/generic/int[13]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10314 || sim/multiplay/generic/int[14]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10315 || sim/multiplay/generic/int[15]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10316 || sim/multiplay/generic/int[16]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10317 || sim/multiplay/generic/int[17]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10318 || sim/multiplay/generic/int[18]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10319 || sim/multiplay/generic/int[19]                        || int&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Types ==&lt;br /&gt;
The types are XDR encoded as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;INT&amp;lt;/tt&amp;gt;:    4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;FLOAT&amp;lt;/tt&amp;gt;: 4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;BOOL&amp;lt;/tt&amp;gt;:  4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;STRING [LEN|STR|PAD]&amp;lt;/tt&amp;gt;:&lt;br /&gt;
** &amp;lt;tt&amp;gt;LEN&amp;lt;/tt&amp;gt;:    4 bytes, length of the decoded string&lt;br /&gt;
** &amp;lt;tt&amp;gt;STR&amp;lt;/tt&amp;gt;:    LEN*4 bytes, encoded string.&lt;br /&gt;
** &amp;lt;tt&amp;gt;PAD&amp;lt;/tt&amp;gt;:    n*4 bytes, padding.&lt;br /&gt;
{{Caution|Due to a bug, all bytes in the &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; field are sent as 4-byte ints (not in the header or the position message). So STR has length LEN*4 and padding (4-LEN%4)*4 bytes, if LEN%4 is not 0.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Multiplayer]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Multiplayer_protocol&amp;diff=78333</id>
		<title>Multiplayer protocol</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Multiplayer_protocol&amp;diff=78333"/>
		<updated>2014-12-17T01:56:46Z</updated>

		<summary type="html">&lt;p&gt;Vin: updated and added xdr information&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== The messages ==&lt;br /&gt;
&lt;br /&gt;
All messages are composed of XDR encoded data. (see [http://www.faqs.org/rfcs/rfc1832.html RFC 1832] for a complete description of XDR). XDR basically means: All data is in network byte order and aligned to the nearest multiple of 4 bytes. Strings are encoded as a zero-terminated array of characters,aligned to the nearest multiple of 4 bytes. Floating point numbers (32 or 64 bit) must be encode in the IEEE standard.&lt;br /&gt;
FlightGear uses XDR encoded messages that are sent via UDP.&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
&lt;br /&gt;
The routines for handling XDR are contained in $FG_SRC/Multiplayer/tiny_xdr.[h|c]xx:&lt;br /&gt;
&lt;br /&gt;
http://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/tiny_xdr.cxx&lt;br /&gt;
&lt;br /&gt;
The different message types supported by the MP protocol are specified in $FG_SRC/MultiPlayer/mpmessages.hxx:&lt;br /&gt;
&lt;br /&gt;
http://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/mpmessages.hxx&lt;br /&gt;
&lt;br /&gt;
The multiplayer system code:&lt;br /&gt;
&lt;br /&gt;
https://gitorious.org/fg/flightgear/blobs/next/src/MultiPlayer/multiplaymgr.cxx&lt;br /&gt;
&lt;br /&gt;
eXternal Data Representation (XDR):&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/External_Data_Representation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The header ==&lt;br /&gt;
The header is always 32 bytes long and contains the following fields in exactly that order:&lt;br /&gt;
&lt;br /&gt;
 |'''Magic'''|'''Version'''|'''MsgId'''|'''MsgLen'''|'''ReplyAddress'''|'''ReplyPort'''|'''Callsign'''|'''Data'''|&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Magic:&lt;br /&gt;
|4 bytes, always 0x46474653 (&amp;quot;FGFS&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
|Version:&lt;br /&gt;
|4 bytes, protocol version, currently 0x00010001 (1.1)&lt;br /&gt;
|-&lt;br /&gt;
|MsgId:&lt;br /&gt;
|4 bytes, defines what data is appended to the header. Can be 0x00000001 for chat messages (deprecated) or&amp;lt;br /&amp;gt;&lt;br /&gt;
0x00000007 for position data - all other values are outdated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|MsgLen:&lt;br /&gt;
|4 bytes, the length of the data. {{Caution|This is not in bytes, see the description of STRING field at the end for more information.}}&lt;br /&gt;
|-&lt;br /&gt;
|ReplyAddress:&lt;br /&gt;
|4 bytes, deprecated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|ReplyPort:&lt;br /&gt;
|4 bytes, deprecated and ignored&lt;br /&gt;
|-&lt;br /&gt;
|Callsign:&lt;br /&gt;
|8 bytes, zero terminated array of characters representing&lt;br /&gt;
the user callsign&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Data of chat messages ==&lt;br /&gt;
The data for chat messages is a zero terminated array of characters. The MsgLen field in the header represents its length. The maximum length is defined to be 256 bytes.&lt;br /&gt;
&lt;br /&gt;
== Data of position messages ==&lt;br /&gt;
The data of position data is more complicated and looks like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|ModelName&lt;br /&gt;
|96 bytes, zero terminated array of characters representing the aircraft model used by the user&lt;br /&gt;
|-&lt;br /&gt;
|time&lt;br /&gt;
|8 bytes, representing the time when this message was generated double&lt;br /&gt;
|-&lt;br /&gt;
|lag  || 8 bytes, time offset for network lag double&lt;br /&gt;
|-&lt;br /&gt;
|PosX || 8 bytes, XDR encoded double value, X-ccordinate of users&amp;lt;br /&amp;gt;&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|PosY || 8 bytes, XDR encoded double value, Y-ccordinate of users&amp;lt;br /&amp;gt;&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|PosZ || 8 bytes, XDR encoded double value, z-ccordinate of users&lt;br /&gt;
position wrt the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|OriX || 4 bytes, XDR encoded float value, X-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|OriY || 4 bytes, XDR encoded float value, Y-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|OriZ || 4 bytes, XDR encoded float value, Z-orientation of the user wrt the earth centered frame, stored in the angle axis representation where the angle is coded into the axis length&lt;br /&gt;
|-&lt;br /&gt;
|VelX || 4 bytes, XDR encoded float value, velocity of the user in X direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|VelY || 4 bytes, XDR encoded float value, velocity of the user in Y direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|VelZ || 4 bytes, XDR encoded float value, velocity of the user in Z direction wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AV3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional angular velocity vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|LA3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional linear accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA1 || 4 bytes, XDR encoded float value, 1. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA2 || 4 bytes, XDR encoded float value, 2. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|AA3 || 4 bytes, XDR encoded float value, 3. part of the three dimensional angular accelaration vector&amp;lt;br /&amp;gt;&lt;br /&gt;
wrt the earth centered frame measured in the earth centered frame&lt;br /&gt;
|-&lt;br /&gt;
|pad || up to 8 bytes for padding the data to a multiple of 8 bytes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This data is followed by '''property-values''', which are encoded in the form '''ID'''|'''Value'''&lt;br /&gt;
&lt;br /&gt;
{{Note|This table is is current for FlightGear 3.2.0.  For the list in the development version, see {{Git link|gitorious|fg/flightgear|master|src/MultiPlayer/multiplaymgr.cxx|text=src/MultiPlayer/multiplaymgr.cxx}}.}}&lt;br /&gt;
&lt;br /&gt;
The following properties are transmitted, but not necessarily all present and not in this order:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID  !!  Property                                              || [[#Types|Types]]&lt;br /&gt;
|-&lt;br /&gt;
|100 || surface-positions/left-aileron-pos-norm                || float&lt;br /&gt;
|-&lt;br /&gt;
|101 || surface-positions/right-aileron-pos-norm               || float&lt;br /&gt;
|-&lt;br /&gt;
|102 || surface-positions/elevator-pos-norm                    || float&lt;br /&gt;
|-&lt;br /&gt;
|103 || surface-positions/rudder-pos-norm                      || float&lt;br /&gt;
|-&lt;br /&gt;
|104 || surface-positions/flap-pos-norm                        || float&lt;br /&gt;
|-&lt;br /&gt;
|105 || surface-positions/speedbrake-pos-norm                  || float&lt;br /&gt;
|-&lt;br /&gt;
|106 || gear/tailhook/position-norm                            || float&lt;br /&gt;
|-&lt;br /&gt;
|107 || gear/launchbar/position-norm                           || float&lt;br /&gt;
|-&lt;br /&gt;
|108 || gear/launchbar/state                                   || string&lt;br /&gt;
|-&lt;br /&gt;
|109 || gear/launchbar/holdback-position-norm                  || float&lt;br /&gt;
|-&lt;br /&gt;
|110 || canopy/position-norm                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|111 || surface-positions/wing-pos-norm                        || float&lt;br /&gt;
|-&lt;br /&gt;
|112 || surface-positions/wing-fold-pos-norm                   || float&lt;br /&gt;
|-&lt;br /&gt;
|200 || gear/gear[0]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|201 || gear/gear[0]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|210 || gear/gear[1]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|211 || gear/gear[1]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|220 || gear/gear[2]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|221 || gear/gear[2]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|230 || gear/gear[3]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|231 || gear/gear[3]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|240 || gear/gear[4]/compression-norm                          || float&lt;br /&gt;
|-&lt;br /&gt;
|241 || gear/gear[4]/position-norm                             || float&lt;br /&gt;
|-&lt;br /&gt;
|300 || engines/engine[0]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|301 || engines/engine[0]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|302 || engines/engine[0]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|310 || engines/engine[1]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|311 || engines/engine[1]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|312 || engines/engine[1]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|320 || engines/engine[2]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|321 || engines/engine[2]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|322 || engines/engine[2]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|330 || engines/engine[3]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|331 || engines/engine[3]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|332 || engines/engine[3]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|340 || engines/engine[4]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|341 || engines/engine[4]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|342 || engines/engine[4]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|350 || engines/engine[5]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|351 || engines/engine[5]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|352 || engines/engine[5]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|360 || engines/engine[6]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|361 || engines/engine[6]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|362 || engines/engine[6]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|370 || engines/engine[7]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|371 || engines/engine[7]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|372 || engines/engine[7]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|380 || engines/engine[8]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|381 || engines/engine[8]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|382 || engines/engine[8]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|390 || engines/engine[9]/n1                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|391 || engines/engine[9]/n2                                   || float&lt;br /&gt;
|-&lt;br /&gt;
|392 || engines/engine[9]/rpm                                  || float&lt;br /&gt;
|-&lt;br /&gt;
|800 || rotors/main/rpm                                        || float&lt;br /&gt;
|-&lt;br /&gt;
|801 || rotors/tail/rpm                                        || float&lt;br /&gt;
|-&lt;br /&gt;
|810 || rotors/main/blade[0]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|811 || rotors/main/blade[1]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|812 || rotors/main/blade[2]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|813 || rotors/main/blade[3]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|820 || rotors/main/blade[0]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|821 || rotors/main/blade[1]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|822 || rotors/main/blade[2]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|823 || rotors/main/blade[3]/flap-deg                          || float&lt;br /&gt;
|-&lt;br /&gt;
|830 || rotors/tail/blade[0]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|831 || rotors/tail/blade[1]/position-deg                      || float&lt;br /&gt;
|-&lt;br /&gt;
|900 || sim/hitches/aerotow/tow/length                         || float&lt;br /&gt;
|-&lt;br /&gt;
|901 || sim/hitches/aerotow/tow/elastic-constant               || float&lt;br /&gt;
|-&lt;br /&gt;
|902 || sim/hitches/aerotow/tow/weight-per-m-kg-m              || float&lt;br /&gt;
|-&lt;br /&gt;
|903 || sim/hitches/aerotow/tow/dist                           || float&lt;br /&gt;
|-&lt;br /&gt;
|904 || sim/hitches/aerotow/tow/connected-to-property-node     || bool&lt;br /&gt;
|-&lt;br /&gt;
|905 || sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign || string&lt;br /&gt;
|-&lt;br /&gt;
|906 || sim/hitches/aerotow/tow/brake-force                    || float&lt;br /&gt;
|-&lt;br /&gt;
|907 || sim/hitches/aerotow/tow/end-force-x                    || float&lt;br /&gt;
|-&lt;br /&gt;
|908 || sim/hitches/aerotow/tow/end-force-y                    || float&lt;br /&gt;
|-&lt;br /&gt;
|909 || sim/hitches/aerotow/tow/end-force-z                    || float&lt;br /&gt;
|-&lt;br /&gt;
|930 || sim/hitches/aerotow/is-slave                           || bool&lt;br /&gt;
|-&lt;br /&gt;
|931 || sim/hitches/aerotow/speed-in-tow-direction             || float&lt;br /&gt;
|-&lt;br /&gt;
|932 || sim/hitches/aerotow/open                               || bool&lt;br /&gt;
|-&lt;br /&gt;
|933 || sim/hitches/aerotow/local-pos-x                        || float&lt;br /&gt;
|-&lt;br /&gt;
|934 || sim/hitches/aerotow/local-pos-y                        || float&lt;br /&gt;
|-&lt;br /&gt;
|935 || sim/hitches/aerotow/local-pos-z                        || float&lt;br /&gt;
|-&lt;br /&gt;
|1001 || controls/flight/slats                                 || float&lt;br /&gt;
|-&lt;br /&gt;
|1002 || controls/flight/speedbrake                            || float&lt;br /&gt;
|-&lt;br /&gt;
|1003 || controls/flight/spoilers                              || float&lt;br /&gt;
|-&lt;br /&gt;
|1004 || controls/gear/gear-down                               || float&lt;br /&gt;
|-&lt;br /&gt;
|1005 || controls/lighting/nav-lights                          || float&lt;br /&gt;
|-&lt;br /&gt;
|1006 || controls/armament/station[0]/jettison-all             || bool&lt;br /&gt;
|-&lt;br /&gt;
|1100 || sim/model/variant                                     || int&lt;br /&gt;
|-&lt;br /&gt;
|1101 || sim/model/livery/file                                 || string&lt;br /&gt;
|-&lt;br /&gt;
|1200 || environment/wildfire/data                             || string&lt;br /&gt;
|-&lt;br /&gt;
|1201 || environment/contrail                                  || int&lt;br /&gt;
|-&lt;br /&gt;
|1300 || tanker                                                || int&lt;br /&gt;
|-&lt;br /&gt;
|1400 || scenery/events                                        || string&lt;br /&gt;
|-&lt;br /&gt;
|1500 || instrumentation/transponder/transmitted-id            || int&lt;br /&gt;
|-&lt;br /&gt;
|1501 || instrumentation/transponder/altitude                  || int&lt;br /&gt;
|-&lt;br /&gt;
|1502 || instrumentation/transponder/ident                     || bool&lt;br /&gt;
|-&lt;br /&gt;
|1503 || instrumentation/transponder/inputs/mode               || int&lt;br /&gt;
|-&lt;br /&gt;
|10001 || sim/multiplay/transmission-freq-hz                   || string&lt;br /&gt;
|-&lt;br /&gt;
|10002 || sim/multiplay/chat                                   || string&lt;br /&gt;
|-&lt;br /&gt;
|10100 || sim/multiplay/generic/string[0]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10101 || sim/multiplay/generic/string[1]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10102 || sim/multiplay/generic/string[2]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10103 || sim/multiplay/generic/string[3]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10104 || sim/multiplay/generic/string[4]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10105 || sim/multiplay/generic/string[5]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10106 || sim/multiplay/generic/string[6]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10107 || sim/multiplay/generic/string[7]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10108 || sim/multiplay/generic/string[8]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10109 || sim/multiplay/generic/string[9]                      || string&lt;br /&gt;
|-&lt;br /&gt;
|10110 || sim/multiplay/generic/string[10]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10111 || sim/multiplay/generic/string[11]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10112 || sim/multiplay/generic/string[12]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10113 || sim/multiplay/generic/string[13]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10114 || sim/multiplay/generic/string[14]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10115 || sim/multiplay/generic/string[15]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10116 || sim/multiplay/generic/string[16]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10117 || sim/multiplay/generic/string[17]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10118 || sim/multiplay/generic/string[18]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10119 || sim/multiplay/generic/string[19]                     || string&lt;br /&gt;
|-&lt;br /&gt;
|10200 || sim/multiplay/generic/float[0]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10201 || sim/multiplay/generic/float[1]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10202 || sim/multiplay/generic/float[2]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10203 || sim/multiplay/generic/float[3]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10204 || sim/multiplay/generic/float[4]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10205 || sim/multiplay/generic/float[5]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10206 || sim/multiplay/generic/float[6]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10207 || sim/multiplay/generic/float[7]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10208 || sim/multiplay/generic/float[8]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10209 || sim/multiplay/generic/float[9]                       || float&lt;br /&gt;
|-&lt;br /&gt;
|10210 || sim/multiplay/generic/float[10]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10211 || sim/multiplay/generic/float[11]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10212 || sim/multiplay/generic/float[12]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10213 || sim/multiplay/generic/float[13]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10214 || sim/multiplay/generic/float[14]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10215 || sim/multiplay/generic/float[15]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10216 || sim/multiplay/generic/float[16]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10217 || sim/multiplay/generic/float[17]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10218 || sim/multiplay/generic/float[18]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10219 || sim/multiplay/generic/float[19]                      || float&lt;br /&gt;
|-&lt;br /&gt;
|10300 || sim/multiplay/generic/int[0]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10301 || sim/multiplay/generic/int[1]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10302 || sim/multiplay/generic/int[2]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10303 || sim/multiplay/generic/int[3]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10304 || sim/multiplay/generic/int[4]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10305 || sim/multiplay/generic/int[5]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10306 || sim/multiplay/generic/int[6]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10307 || sim/multiplay/generic/int[7]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10308 || sim/multiplay/generic/int[8]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10309 || sim/multiplay/generic/int[9]                         || int&lt;br /&gt;
|-&lt;br /&gt;
|10310 || sim/multiplay/generic/int[10]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10311 || sim/multiplay/generic/int[11]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10312 || sim/multiplay/generic/int[12]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10313 || sim/multiplay/generic/int[13]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10314 || sim/multiplay/generic/int[14]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10315 || sim/multiplay/generic/int[15]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10316 || sim/multiplay/generic/int[16]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10317 || sim/multiplay/generic/int[17]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10318 || sim/multiplay/generic/int[18]                        || int&lt;br /&gt;
|-&lt;br /&gt;
|10319 || sim/multiplay/generic/int[19]                        || int&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Types ==&lt;br /&gt;
The types are XDR encoded as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;INT&amp;lt;/tt&amp;gt;:    4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;FLOAT&amp;lt;/tt&amp;gt;: 4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;BOOL&amp;lt;/tt&amp;gt;:  4 bytes, send unconditionally&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;STRING [LEN|STR|PAD]&amp;lt;/tt&amp;gt;:&lt;br /&gt;
** &amp;lt;tt&amp;gt;LEN&amp;lt;/tt&amp;gt;:    4 bytes, length of the decoded string&lt;br /&gt;
** &amp;lt;tt&amp;gt;STR&amp;lt;/tt&amp;gt;:    LEN*4 bytes, encoded string.&lt;br /&gt;
** &amp;lt;tt&amp;gt;PAD&amp;lt;/tt&amp;gt;:    n*4 bytes, padding.&lt;br /&gt;
{{Caution|Due to a bug, all bytes in the &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; field are sent as 4-byte ints (not in the header or the position message). So STR has length LEN*4 and padding (4-LEN%4)*4 bytes, if LEN%4 is not 0.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Multiplayer]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38322</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38322"/>
		<updated>2011-12-23T12:15:59Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A namespace is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol (variable) is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kept in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses wanting to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
Here, houseX is the enclosing namespace/context, i.e. &amp;quot;bath&amp;quot; is a member or &amp;quot;field&amp;quot; of the namespace.&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace. Imagine a namespace to be a container with its own variables and scope. So certain variables are only valid within that particular namespace.&lt;br /&gt;
&lt;br /&gt;
Otherwise, you would have to use different symbols with explicit naming conventions, such as:&lt;br /&gt;
&lt;br /&gt;
 house1_bath&lt;br /&gt;
 house2_bath&lt;br /&gt;
 house3_bath&lt;br /&gt;
&lt;br /&gt;
These naming conventions can become awkward pretty quickly.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only such &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable).&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default be specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace, 'x' will only be valid and visible during the lifetime of function, i.e. at execution time.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In Nasal, a namespace is just a conventional hash:&lt;br /&gt;
&lt;br /&gt;
 var foo = {};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To add members or fields to this &amp;quot;context&amp;quot; (or namespace), you can use several different notations:&lt;br /&gt;
&lt;br /&gt;
 foo.altitude = 100;&lt;br /&gt;
 foo[&amp;quot;altitude&amp;quot;] = 100;&lt;br /&gt;
&lt;br /&gt;
or even specify fields during initialization:&lt;br /&gt;
&lt;br /&gt;
 var foo = { altitude:100 };&lt;br /&gt;
&lt;br /&gt;
In order to access these fields or &amp;quot;members&amp;quot; of a namespace, you need to provide the valid namespace first:&lt;br /&gt;
&lt;br /&gt;
 print ( foo.altitude );&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
In object oriented programming, this concept is very powerful because you cannot only have hash-specific variables but also hash-specific functions. This makes it possible to create new objects by using a template hash and inheriting fields and behavior (methods).&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#Namespaces here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object (house) must be created using the template, and then the member functions (methods) can be called for that object.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#More_on_methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;br /&gt;
&lt;br /&gt;
== Resources ==&lt;br /&gt;
&lt;br /&gt;
This article would not have been possible without FG Forum Member Hooray:&lt;br /&gt;
&lt;br /&gt;
http://www.flightgear.org/forums/viewtopic.php?f=30&amp;amp;t=14737&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38303</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38303"/>
		<updated>2011-12-23T02:18:13Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Exception handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Namespaces_and_Methods#Methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38302</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38302"/>
		<updated>2011-12-23T02:15:37Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* More on methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Namespaces_and_Methods#Methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38301</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38301"/>
		<updated>2011-12-23T02:14:12Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Exception handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Namespaces_and_Methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38300</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38300"/>
		<updated>2011-12-23T02:13:57Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* More on methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Namespaces_and_Methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38299</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38299"/>
		<updated>2011-12-23T02:13:20Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* More Information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#Namespaces here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#More_on_methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38298</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38298"/>
		<updated>2011-12-23T02:13:07Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#Namespaces here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#More_on_methods here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38297</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38297"/>
		<updated>2011-12-23T02:12:30Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#Namespaces here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''More info ''[http://wiki.flightgear.org/Nasal_scripting_language#More_on_methods here]''.'''&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38296</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38296"/>
		<updated>2011-12-23T02:10:46Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Click ''[http://wiki.flightgear.org/Nasal_scripting_language#Namespaces here]'' for more information.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38295</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38295"/>
		<updated>2011-12-23T02:10:01Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Click ''[http://wiki.flightgear.org/Nasal_scripting_language#Namespaces here]'' for more information.&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38294</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38294"/>
		<updated>2011-12-23T02:08:04Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Variables - Advanced Uses */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38293</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38293"/>
		<updated>2011-12-23T02:07:23Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38292</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38292"/>
		<updated>2011-12-23T02:06:59Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
'''''More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].'''''&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38291</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=38291"/>
		<updated>2011-12-23T02:06:14Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[[Talk:Nasal_scripting_language|discussion]]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nasal = Not another scripting language!==&lt;br /&gt;
&lt;br /&gt;
 The short summary is that Nasal is a scripting language that is tightly integrated with FlightGear itself, &lt;br /&gt;
 and provides a very easy way to manipulate the property tree, which is the core data structure within the &lt;br /&gt;
 simulator that expose all important internal runtime state of FlightGear. &lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a very powerful functional scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal [[Property Tree Intro|FlightGear properties]], accessing internal data via extension functions, creating GUI dialogs and much more. &lt;br /&gt;
&lt;br /&gt;
Nasal uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming (OOP), Nasal uses an internal garbage collector so that no manual memory management is required by the programmer. &lt;br /&gt;
&lt;br /&gt;
People familiar with other programming languages, and scripting languages like JavaScript in particular, are usually able to learn Nasal rather quickly. FlightGear provides a rich library of simulation-specific and general-purpose functions that can be accessed by Nasal scripts.&lt;br /&gt;
&lt;br /&gt;
Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls, and even in [[Howto: Nasal in scenery object XML files|scenery objects]]). Nasal is platform independent and designed to be thread safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Some success stories ===&lt;br /&gt;
These were taken from the developers mailing list:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Nasal is *very* well designed, compact, and efficient.  It is used heavily throughout many areas of FlightGear.&amp;quot;&lt;br /&gt;
* &amp;quot;It's interesting though how much nasal you can actually get away with using without making a blip on frame rates.  Nasal is *very* efficient and powerful for being an interpreted script language.&amp;quot;&lt;br /&gt;
* &amp;quot;FlightGear needed a built-in scripting language, and it has one. A compact, clean, elegant and fast one, Nasal extension functions interface perfectly to the property tree, the event manager, the built-in XML parser etc. Nasal is very tightly integrated in fgfs and used all over the place.&amp;quot;&lt;br /&gt;
* &amp;quot;There's no question that scripting languages are good; fgfs has a lot of Nasal code now. In my profiling I have never seen the nasal interpreter as a hot spot&amp;quot;&lt;br /&gt;
* &amp;quot;I'm a simple content contributor with very little background in programming. When I made my first Aircraft (the bf109) I was confronted with the need to deploy slats automatically at a given speed. I din't want to embed C++ code or had such a complex script that the error messages in FG wouldn't help me and I previously only used a bit of python. I looked at some Nasal scripts and within a few hours it worked. I was impressed how easy it is to write even complex Nasal scripts. Later I started developing the walker feature that made it possible to walk around in the scenery, all with nasal. Stuart kindly enhanced the walker and added an animation system to it (see bluebird), again with nasal. Others have made Flight computers with it (see V-22 and Su-37). Nasal is a worthy tool&amp;quot;&lt;br /&gt;
* &amp;quot;I used Nasal to build several rather complex systems, like Fuel System, Stab Augmentation System, Autopilot Logic, Terrain Avoidance Radar, Radar Warning Receiver and much more, and yes, I love Nasal too. Learning Nasal use was easy and fun and I din't found any limitation yet.&amp;quot;&lt;br /&gt;
* There are many vital parts of FlightGear currently coded in nasal.  There are also random bits of nasal code scattered around in joystick configurations, instrument and aircraft models, scenery models...  everywhere.&lt;br /&gt;
* &amp;quot;We have an entire directory full of Nasal 'function' libraries now, and I'm quite happy using them instead of rolling my own duplicate functionality.&amp;quot;&lt;br /&gt;
* Nearly every sophisticated Aircraft uses some kind of Nasal, be it Effects like tyre smoke or important functionalities like Engine and electric management, The Bluebird FDM is completely written in Nasal, vital parts of the V-22 Osprey rely on it, Flyby and Model View wouldn't work anymore, no more interactive objects in the scenery, lots of the MP System would be gone, ... Nasal is THE tool which makes FG development fun and adds nearly unlimited possibilities.  If you need an example, look at the Bluebird animated walker, all done in Nasal.&amp;quot;&lt;br /&gt;
* &amp;quot;there are good reasons to use Nasal - first of all the user base which regularly compiles their own code is small, whereas people do install addon packages - so I get a lot more feedback and test results. Second that one usually can't really crash the whole system from Nasal. Third, it's very easy to quickly try something and very maintenance-friendly. Fourth, you can actually start developing something without knowing how the core code ties together - which I suppose takes a lot of time to learn.  And so on.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard-coding every instrument in C++ instead of nasal means only developers following/building the latest cvs  head code get to use whatever until the next release cycle.&amp;quot;&lt;br /&gt;
* &amp;quot;Hard coding every instrument/flight control in C++ means my WW-II storch (et.al.) is stuck with an autobrake functionality it doesn't have nor need.&amp;quot;&lt;br /&gt;
* &amp;quot;I think it boils down to the fact that we have two approaches that can accomplish the same thing.  The C/C++ approach offers high performance but there is a dependence on when the C/C++ code was added to FlightGear.  The Nasal approach offers fast prototyping, flexibility, and more (but not complete) independence from the C/C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;A basic problem with C++ functions is it is hard/impossible to override them for a special purpose. Writing in pure nasal allows function name hijacking and other tricks that can't be used on C++ code.&amp;quot;&lt;br /&gt;
* &amp;quot;Given the fact that FG is platform independent, I don't know if the embedded C++ is doing the same on Windows, Linux, PPC and intel Macs. Apart from the fact that if I was able to code c++ I would embed it to FG rather than in an Aircraft specific script&amp;quot;&lt;br /&gt;
* &amp;quot;If we ported Nasal code over to C++ we'd lose the ability to change small things &amp;quot;on the fly&amp;quot; without compiling over and over again. We'd also lose good programmers, who prefer scripting over C++. Aircraft creation would not be customizable etc etc.&amp;quot;&lt;br /&gt;
* &amp;quot;The argument against Nasal is essentially that C++ is faster than Nasal - which, everything else being equal, is certainly correct. But highly specialized Nasal code written for a particular problem outperforms general  purpose C++ code - I've given several examples in the past. If someone were e.g. to add movement to Nasal spawned models by adding a velocity property, I'm not sure it would outperform my Nasal quadtree-sorted adaptive range code which priorizes movement for things actually inside the field of view. Of course, if you'd hard-code that specialized algorithm, it would be faster than the Nasal version - but then you couldn't apply it to other problems any more.&amp;quot;&lt;br /&gt;
* &amp;quot;How many airplane developer will you loose if you remove the Nasal engine from FGFS because they can write Nasal code but not C++ code?&amp;quot;&lt;br /&gt;
* &amp;quot;The algorithm being equal, I don't think there's a question that C++ is faster (I doubt the factor 10 though - that seems to be an extreme case). Everything else being equal, I also don't think there's a question that Nasal code is more accessible. And I would base any decision what to hard-code and what not on that balance.&amp;quot;&lt;br /&gt;
* &amp;quot;Nasal is just much better suited for FlightGear than many alternatives because of it's size, processing speed and because a number of FlightGear core developers have a good idea what's going on.&amp;quot;&lt;br /&gt;
* &amp;quot;In theory we could even use VBScript but Nasal has proven to be valuable for almost 10 years, so no reason to change or add another scripting language. Besides, if you know JavaScript then learning Nasal would take little effort.&amp;quot;&lt;br /&gt;
* &amp;quot;The pool of people with commit rights to the core C++ code is very, very small.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal really is an excellent choice for prototyping and implementing new features and even completely new systems in FlightGear. &lt;br /&gt;
&lt;br /&gt;
For example, the [[bombable]] script implements &amp;quot;dog fighting&amp;quot; support on top of FlightGear, without ANY changes to the C++ side of the code, just by using some fairly advanced scripted code (implemented in the built-in Nasal programming language). You can basically imagine it like a &amp;quot;MOD&amp;quot; of FlightGear. In other words, the bombable script creates a completely new &amp;quot;mode&amp;quot; in FlightGear.&lt;br /&gt;
&lt;br /&gt;
No matter if it's scenery, aircraft, AI scenarios or whatever: many things that were originally never planned to be supported by FlightGear core developers, are now implicitly supported because of the lose coupling between highly configurable and flexible systems, such as the property tree and the Nasal scripting language.&lt;br /&gt;
&lt;br /&gt;
So we are really standing on the shoulders of giants here, because we are now -after 10+ years- in the position to create significant new features (and even completely new systems in FlightGear) within the constraints of the FlightGear base package, without even touching the C++ source code at all - simply because FlightGear has become so flexible and extensible.&lt;br /&gt;
&lt;br /&gt;
All of this became possible by some important architectural decisions, such as for example the use of XML and plain text files for pretty much all configuration files in FlightGear (and thus open file formats in general), a publicly accessible tree of state variables that can be easily inspected and modified at runtime (the property tree). Similarly, the decision to embed a scripting language that can be used for scripting the entire simulator was another important decision.&lt;br /&gt;
&lt;br /&gt;
In FlightGear, Nasal is the most accessible method of customizing the whole simulator to a very high degree. Nasal code can be easily edited using a conventional text editor, there are no special tools required: Nasal source code is interpreted, compiled to bytecode and run by the Nasal &amp;quot;virtual machine&amp;quot; using FlightGear itself. &lt;br /&gt;
&lt;br /&gt;
The emerging [[A local weather system|Local weather]] system was entirely prototyped in Nasal space, and is now being increasingly augmented by moving performance-critical functions to C++ space instead.&lt;br /&gt;
&lt;br /&gt;
Using Nasal, it is even possible to create entirely scripted flights and smart &amp;quot;AI bots&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 I have something here that I think is kind of fun.  I've been fiddling with&lt;br /&gt;
 this off and on since last fall and decided it was time to clean it up a bit&lt;br /&gt;
 and quit hording all the fun for myself.  Basically I have taken the F-14b&lt;br /&gt;
 and created a high performance Navy &amp;quot;drone&amp;quot; out of it.  It can auto-launch&lt;br /&gt;
 from a carrier, auto fly a route (if you've input one) and can do circle&lt;br /&gt;
 holds (compensating for wind.)  I've added a simulated&lt;br /&gt;
 gyro stabilized camera that will point at anything you click on and then&lt;br /&gt;
 hold that view steady no matter what the airplane does (similar to what real&lt;br /&gt;
 uav's can do.)  Finally, you can command it to return home and it will find&lt;br /&gt;
 the carrier, setup a reasonable approach and nail the landing perfectly&lt;br /&gt;
 every time (factoring in wind, carrier speed, etc.): http://www.flightgear.org/uas-demo/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 03/2009, there were approximately 170.000 lines of reported Nasal source code in the FlightGear base package [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg21333.html], compared to 2006 this is almost a rate of growth of 600% within 3 years [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg01728.html]. This illustrates the sheer adoption rate Nasal is experiencing in FlightGear.&lt;br /&gt;
&lt;br /&gt;
(As of 10/2011, the FlightGear base package contained 326.000 lines of Nasal source code in *.nas files)&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage patterns. &lt;br /&gt;
Thus, you may also want to have a look here:&lt;br /&gt;
&lt;br /&gt;
* [http://plausible.org/nasal/lib.html core language/library documentation] &lt;br /&gt;
* [http://plausible.org/nasal/sample.nas annotated source code examples]&lt;br /&gt;
* [http://plausible.org/nasal/doc.html Nasal design document]&lt;br /&gt;
* [http://www.plausible.org/nasal/flightgear.html a helpful tutorial about using Nasal in FlightGear].&lt;br /&gt;
&lt;br /&gt;
In addition, the [http://gitorious.org/fg/fgdata/trees/master/Nasal Nasal directory] in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://gitorious.org/fg/fgdata/trees/master/Nasal].&lt;br /&gt;
&lt;br /&gt;
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer or refine existing ones. If you would like to learn more about existing Nasal modules in FlightGear, you may want to check out [[Nasal Modules]].&lt;br /&gt;
&lt;br /&gt;
If you are a developer and interested in extending Nasal, you may want to check out [[Howto:Extending Nasal]].&lt;br /&gt;
&lt;br /&gt;
Many short &amp;quot;howto&amp;quot;-style tutorials on Nasal programming can be found in the [[Category:Nasal|Nasal category]].&lt;br /&gt;
&lt;br /&gt;
== Some words on Nasal for fellow C++ programmers ==&lt;br /&gt;
&lt;br /&gt;
Compared to C++, there is really nothing &amp;quot;low quality&amp;quot; about Nasal per se: Nasal is just the &amp;quot;script glue&amp;quot; that connects different parts of the simulator: Many Nasal scripts leverage C++ code - and it is very easy to add new C++ code that can be called from Nasal. &lt;br /&gt;
&lt;br /&gt;
History has shown, that most code in FlightGear will eventually be made more configurable and more accessible, this usually happens in the same steps: 1) replacing static variables with variables stored in the property tree, 2) using listeners to get update notifications for important variables, 3) fully exposing a &amp;quot;control&amp;quot; interface by making it accessible it in the property tree, 4) providing scripting hooks.&lt;br /&gt;
&lt;br /&gt;
Even if you should know C or C++ already, Nasal probably remains the most accessible and the most powerful method for customizing the simulator, simply because it is extremely easy and fast to get started, you don't need an &amp;quot;integrated development environment&amp;quot;, you don't need to install compilers and you don't need to satisfy any 3rd party dependencies; bottom line being: if you can run FlightGear, you can also run Nasal and create new code.&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal code is fairly abstract code, too. Once you start looking at some existing Nasal scripts, you will see that it is also fairly high level code, much more high level than C++ - so Nasal has a much higher density of code, too. Nasal's role in FlightGear really is like JavaScript's role in Firefox, where it is also used for many/most core-related logics (CSS/XUL). &lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Obviously, C++ code will usually be faster than the corresponding Nasal code. But, while performance is not a design goal, Nasal isn't especially slow either. For example, early benchmarks of the garbage collector showed it as faster than perl's reference counter, and its number crunching performance is on par with python. But in all cases, simplicity, transparency and a sane feature set are preferred over speed in Nasal. &lt;br /&gt;
&lt;br /&gt;
Nasal was specifically designed for use as an extension language in an larger project such as FlightGear. The problem with many otherwise excellent languages in this environment is that they are huge. Perl and python are great, but enormous. Even their &amp;quot;core&amp;quot; interpreters and library code are larger than most projects that require an embedded language. They cannot be readily shipped with their host application and need to be installed system-wide. This is a pain and a compatibility hassle. &lt;br /&gt;
&lt;br /&gt;
The real goal with Nasal is to have a language that supports most &amp;quot;normal&amp;quot; programming idioms (objects, functions, arrays, hashes) while avoiding the bloat that comes from &amp;quot;platform&amp;quot; scripting languages like perl, python, ruby and php.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Garbage collection ===&lt;br /&gt;
Nasal garbage collects runtime storage, so the programmer need not worry about manual allocation, or even circular references. The current implementation is a simple mark/sweep collector, which should be acceptable for most applications. Future enhancements will include a &amp;quot;return early&amp;quot; capability for latency-critical applications. The collector can be instructed to return after a certain maximum delay, and be restarted later. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As far as speed goes, the last any benchmarking Nasal was done, it was about as fast as Perl 5 or Python 2.2 at most things.  It's garbage collector was faster, its symbol lookup about the same or slightly faster, and its bytecode interpreter somewhat slower.&lt;br /&gt;
&lt;br /&gt;
=== Thread safety ===&lt;br /&gt;
Unlike almost all other script interpreters (and unlike the FlightGear/Nasal interface itself) , Nasal is thread safe and scalable when called from multiple CPU threads (as opposed to the userspace interpreter threads implemented by Ruby). &lt;br /&gt;
&lt;br /&gt;
No special treatment is required (as for perl, which clones a separate interpreter with separate data for each thread and uses locking around specifically-designated shared data) and the threads can be scheduled simultaneously. There is no global lock on the interpreter, as used by Python or Lua. The only limit on scalability is garbage collection, which must block all interpreter threads before running. &lt;br /&gt;
&lt;br /&gt;
When running threaded code, Nasal provides &amp;quot;minimal threadsafety&amp;quot;, meaning that the interpreter itself can be safely called from multiple CPU threads without risk of corrupting or deadlocking the interpreter internals. Multithreaded operations are therefore &amp;quot;safe&amp;quot;, although they are not guaranteed to be atomic. In particular, poorly synchronized insertions into containers can &amp;quot;drop&amp;quot; objects into oblivion (which is OK from an interpreter stability standpoint, since the GC will clean them up normally). Nasal itself provides no synchronization primitives to address this; thread architecture is a &amp;quot;top-level&amp;quot; design job, and Nasal is intended to be an extension language in a larger project. Choice of synchronization mechanisms is going to be highly application dependent. &lt;br /&gt;
&lt;br /&gt;
=== Exception handling ===&lt;br /&gt;
Like python, nasal supports exception handling as a first-class language feature, with built-in runtime-inspectable stack trace. Rather like perl, however, there is no special &amp;quot;try&amp;quot; syntax for exception handling, nor inheritance-based catching semantics. Instead, you use the call() builtin to invoke a function object and inspect the results to determine what error was thrown (either with the die() builtin or via an internal runtime error) and what the stack trace looked like. Elaborate exception handling isn't really appropriate for embedded scripting languages.&lt;br /&gt;
&lt;br /&gt;
=== High level programming ===&lt;br /&gt;
&lt;br /&gt;
Thus, programmers already familiar with C++ shouldn't just disregard Nasal as a &amp;quot;toy&amp;quot; that doesn't seem suitable for serious development: some of the more complex Nasal scripts can literally make one's head spin around and it would quite obviously take much more C++ or Java code to implement the same features, while sacrificing all the flexibility and power that a scripting language offers. &lt;br /&gt;
&lt;br /&gt;
Some features can certainly be more easily implemented in Nasal space, than in C++ space. Often, the Nasal solution is &amp;quot;on par&amp;quot; with similar solutions in C++.&lt;br /&gt;
&lt;br /&gt;
=== Accessibility ===&lt;br /&gt;
&lt;br /&gt;
For instance, Nasal code cannot only be easily run and contributed by all users, but it can also be easily reused and maintained by other users. This means, that given the number of active C++ developers, compared to the number of base package contributors, your Nasal code is more likely to be actively maintained by fellow users if it is written in Nasal. &lt;br /&gt;
&lt;br /&gt;
In other words, if there are some experimental features you'd like to explore, Nasal is an excellent way to ensure that other FlightGear '''users''' can easily test your new features. This could be witnessed during the development of the local weather system or the bombable addon,too.&lt;br /&gt;
&lt;br /&gt;
This is in stark contrast to features developed solely in C++ space, because these can usually only be tested by people able to build FlightGear from source, especially if your code isn't yet in the main repository, where it would eventually be available in the form of a binary snapshot.&lt;br /&gt;
&lt;br /&gt;
Obviously, none of this is to say that Nasal is the perfect solution for any problem, there are many things for which Nasal isn't necessarily a perfect choice, such as low level code for example (i.e. rendering).&lt;br /&gt;
&lt;br /&gt;
On the other hand, Nasal really is a powerful tool in FlightGear, and if you find that something should, but cannot, be done in Nasal space, it is extremely easy to add support for new features to the Nasal engine using extension functions or property listeners to trigger C/C++ code.&lt;br /&gt;
&lt;br /&gt;
== Creating new Scripts ==&lt;br /&gt;
&lt;br /&gt;
Nasal scripts need to be plain text files, saved with a *.nas extension.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Generally, aircraft specific Nasal scripts reside in the corresponding aircraft's folder (or a corresponding /Nasal subfolder) where they are usually included by adding a corresponding &amp;lt;nasal&amp;gt; tag to the aircraft-set.xml file (see [[Writing_simple_scripts_in_%22nasal%22|Writing simple scripts in &amp;quot;nasal&amp;quot;]]). Also see the section on [[Nasal_scripting_language#Namespaces|namespaces]] which contains more specific examples.&lt;br /&gt;
&lt;br /&gt;
=== Instrument specific Nasal code ===&lt;br /&gt;
&lt;br /&gt;
While instrument specific scripts are saved within the instrument's folder (as previously mentioned, Nasal scripts can also be embedded in various other XML files), Nasal scripts driving shared instruments are generally stored in [[$FG ROOT]]/Aircraft/Generic/&lt;br /&gt;
&lt;br /&gt;
=== Nasal code as bindings in XML files ===&lt;br /&gt;
Nasal scripts can also be used as &amp;quot;binding&amp;quot; objects, and can therefore appear anywhere in a configuration file (keyboard, mouse and joystick bindings, etc...) that accepts a &amp;lt;binding&amp;gt; tag. The relevant command type is &amp;quot;nasal&amp;quot;, and you place your Nasal code inside of the &amp;lt;script&amp;gt; tag: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;binding&amp;gt;&lt;br /&gt;
  &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
  &amp;lt;script&amp;gt;&lt;br /&gt;
   print(&amp;quot;Binding Invoked!&amp;quot;);&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/binding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above invokes the print() function. This is a simple extension function that simply prints out its arguments, in order, to the FlightGear console as a single-line log entry. It is useful for debugging, but little else. &lt;br /&gt;
&lt;br /&gt;
=== System-wide Nasal code ===&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are not specific to certain aircraft, instruments or other uses, generally reside in the system-wide [[$FG ROOT]]/Nasal directory.&lt;br /&gt;
&lt;br /&gt;
Nasal scripts that are placed inside [[$FG ROOT]]/Nasal (with a *.nas extension) are automatically loaded and run during FlightGear startup. &lt;br /&gt;
&lt;br /&gt;
=== Nasal sub modules ===&lt;br /&gt;
&lt;br /&gt;
As of 06/2011, FlightGear also supports so called Nasal &amp;quot;sub modules&amp;quot; which may reside in their own sub folder under $FG_ROOT/Nasal/ and which provide support for on-demand loading at runtime by toggling properties.&lt;br /&gt;
&lt;br /&gt;
Some advantages are:&lt;br /&gt;
&lt;br /&gt;
* Nasal files can be grouped neatly instead of all scripts being mixed up in a single fgdata/Nasal directory. Grouping makes a lot of sense for modules consisting of several scripts - local weather is the best example.&lt;br /&gt;
* Guaranteed loading sequence. Submodules are loaded _after_ the main fgdata/Nasal scripts, so they can rely on all fgdata/Nasal content to be already present. No more need for awkward listener callbacks, just to make sure that basic &amp;quot;props&amp;quot; or &amp;quot;gui&amp;quot; modules are available.&lt;br /&gt;
* Finally, users have the option to disable loading modules. Unfortunately, just loading scripts (code/data) into memory already causes certain _run-time_ performance effects - even if the Nasal code was never executed (so even when all listeners/timers were disabled).&lt;br /&gt;
&lt;br /&gt;
Please note that there is  a difference between the _individual_ Nasal files in fgdata/Nasal and files belonging to a common Nasal _module in general (no matter whether loaded at run-time or loaded at start-up using a &amp;quot;&amp;lt;nasal&amp;gt;&amp;quot; tag).&lt;br /&gt;
&lt;br /&gt;
The individual Nasal files in fgdata/Nasal have an own namespace _each_. The namespace get's the name of the Nasal file itself. So if you have a &amp;quot;gui.nas&amp;quot; in the directory, then you can reference a symbol &amp;quot;foo&amp;quot; using &amp;quot;gui.foo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nasal modules also have a single namespace. But all files belonging to the module share this _single_ namespace. The name of their namespace is made from its directory (for the run-time loadable modules), or from the specific tag given below the &amp;lt;nasal&amp;gt; XML element, which are often used for a/c specific modules (e.g. &amp;lt;nasal&amp;gt;&amp;lt;ufo&amp;gt;...&amp;lt;/ufo&amp;gt;&amp;lt;/nasal&amp;gt; creates the ufo Nasal namespace in ufo-set.xml).&lt;br /&gt;
&lt;br /&gt;
'''So each Nasal file in a new Nasal &amp;quot;module&amp;quot; folder now shares the same namespace.'''&lt;br /&gt;
&lt;br /&gt;
For more information on Nasal sub modules, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg32657.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg33458.html].&lt;br /&gt;
&lt;br /&gt;
=== User specific Nasal scripts ===&lt;br /&gt;
&lt;br /&gt;
It's also possible to put Nasal files into $FG_HOME/Nasal/, that is: ~/.fgfs/Nasal/ on Unix, and %APPDATA%\flightgear.org\Nasal\ on MS Windows. This has the following advantages:&lt;br /&gt;
&lt;br /&gt;
* one doesn't have to mix local extensions with standard files&lt;br /&gt;
* one is less likely to lose such local additions when upgrading&lt;br /&gt;
* one doesn't need write permission to $FG_ROOT/Nasal/ or&lt;br /&gt;
* one doesn't have to become &amp;quot;root&amp;quot; to edit such files&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read after all the files in $FG_ROOT/Nasal/, so one can safely use elements of files like props.nas (props.Node), or globals.nas (setlistener() without leading underscore).&lt;br /&gt;
&lt;br /&gt;
The files are guaranteed to be read in alphabetic order. So, if there are two files where one depends on the other, just name them appropriately.&lt;br /&gt;
&lt;br /&gt;
The contents of each file are added to a namespace derived from the filename. So, all functions and variables of a file ~/.fgfs/nasal/local.nas will be added to nasal namespace &amp;quot;local&amp;quot;, and a function test() is globally accessible as local.test().&lt;br /&gt;
&lt;br /&gt;
It's possible to extend a standard module like &amp;quot;math&amp;quot; with definitions in ~/.fgfs/Nasal/math.nas, though this should, of course, not be exploited by code that is to be submitted to cvs.&lt;br /&gt;
&lt;br /&gt;
== Hello world ==&lt;br /&gt;
&lt;br /&gt;
A simple hello world example in Nasal would be:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print('Hello World!');&lt;br /&gt;
&lt;br /&gt;
This will show the &amp;quot;Hello World&amp;quot; string during startup in the console window. The hash sign (#) just introduces comments (i.e. will be ignored by the interpreter).&lt;br /&gt;
&lt;br /&gt;
Note: Script-specific symbols such as global variables (or functions) will be put into a scope (namespace) based on the script's name, scripts embedded via aircraft-set.xml files can separately specify a corresponding module name (see [[Howto: Make an aircraft]] for details).&lt;br /&gt;
&lt;br /&gt;
Strings in Nasal can also use double quotes which support escaping:&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 print(&amp;quot;Hello\nWorld!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Double quotes support typical escape sequences:&lt;br /&gt;
&lt;br /&gt;
* \n 	Newline&lt;br /&gt;
* \t	Horizontal Tab&lt;br /&gt;
* \v	Vertical Tab&lt;br /&gt;
* \b	Backspace&lt;br /&gt;
* \r	Carriage Return&lt;br /&gt;
* \f	Form feed&lt;br /&gt;
* \a	Audible Alert (bell)&lt;br /&gt;
* \\	Backslash&lt;br /&gt;
* \?	Question mark&lt;br /&gt;
* \'	Single quote&lt;br /&gt;
* \&amp;quot;	Double quote&lt;br /&gt;
&lt;br /&gt;
For example, to print a new line, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
To print a quoted string, use:&lt;br /&gt;
&lt;br /&gt;
 print (&amp;quot;\&amp;quot;quoted string\&amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
Single quotes treat everything as literal except for embedded single quotes (including embedded whitespace like newlines).&lt;br /&gt;
&lt;br /&gt;
Nasal strings are always arrays of bytes (never characters: see the utf8 library if you want character-based equivalents of substr() et. al.). They can be indexed just like in C (although note that there is no nul termination -- get the length with size()):&lt;br /&gt;
&lt;br /&gt;
== Editing code files ==&lt;br /&gt;
&lt;br /&gt;
Note that there is currently no way to tell FlightGear to reload Nasal scripts from the global Nasal directory at runtime, so in order to see changes take effect, you will have to exit and restart FlightGear for the time being. Note that there are some workarounds available, see: [[Nasal_scripting_language#Loading.2Freloading_Nasal_code_without_re-starting_Flightgear|reloading Nasal code without re-starting FlightGear]].&lt;br /&gt;
&lt;br /&gt;
Also, note that as of 05/2009, Nasal in FlightGear does not yet support any form of dependency resolution. In other words, there's no &amp;quot;import&amp;quot;, &amp;quot;require&amp;quot; or &amp;quot;include&amp;quot; directive - this is also why most code in FlightGear is wrapped inside a _setlistener() call instead, which in turn waits for a FlightGear signal before executing the code (see below for details).&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
Nasal scripts should make use of the var keyword when declaring variables. The &amp;quot;var&amp;quot; keyword makes a variable guaranteed to be local. Nasal, natively provides support for scalars (numbers, strings), lists (arrays, vectors) and hashes (objects or dictionaries), more complex data structures (such as trees) can be built using vectors or hashes.&lt;br /&gt;
&lt;br /&gt;
 var w=100;     # w is a local numerical variable&lt;br /&gt;
 var x=&amp;quot;hello&amp;quot;; # x is a local string variable&lt;br /&gt;
 var y=[];      # y is a local vector (array)&lt;br /&gt;
 var z={};      # z is a local hash (dictionary or table) - also used for OOP&lt;br /&gt;
&lt;br /&gt;
Nasal supports a &amp;quot;nil&amp;quot; value for use as a null pointer equivalent:&lt;br /&gt;
&lt;br /&gt;
 var foo=nil; &lt;br /&gt;
&lt;br /&gt;
Also, note that Nasal symbols are case-sensitive, these are all different variables:&lt;br /&gt;
&lt;br /&gt;
 var show = func(what) {print(what,&amp;quot;\n&amp;quot;);}&lt;br /&gt;
 var abc=1; # these are all different symbols&lt;br /&gt;
 var ABC=2; # different from abc &lt;br /&gt;
 var aBc=3; # different from abc and ABC&lt;br /&gt;
 &lt;br /&gt;
 show(abc);&lt;br /&gt;
 show(ABC);&lt;br /&gt;
 show(aBc);&lt;br /&gt;
&lt;br /&gt;
Please note that functions assigned to variables are no exception. If you write code without using &amp;quot;var&amp;quot; on variables, then you risk (often hard to debug) breakage at a later time because you may be overwriting symbols in another namespace. &lt;br /&gt;
&lt;br /&gt;
So functions bound to variables should use the &amp;quot;var&amp;quot; keyword as well:&lt;br /&gt;
&lt;br /&gt;
 var hello = func { &lt;br /&gt;
   print(&amp;quot;hello\n&amp;quot;); &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But there's another reason why &amp;quot;var&amp;quot; should be used consequently, even if a variable is safe enough from later side effects, because it has a relatively specific or unique name: The &amp;quot;var&amp;quot; keyword makes&lt;br /&gt;
reading code for others (and for the author after some time) easier, as it makes clear: &amp;quot;this variable starts its life *HERE*&amp;quot;. No need to search around to see whether assigning a value to it means something to other code outside or not. Also, with an editor offering proper syntax highlighting reading such code is actually easier, despite the &amp;quot;noise&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The problem with nasal code that does not make use of the var keyword is, that it can break other code, and with it the whole system, but no Nasal error message will point you there, as it's syntactically and semantically correct code. Just doing things that it wasn't supposed to do.&lt;br /&gt;
For a more in-depth discussion, please see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg13557.html].&lt;br /&gt;
&lt;br /&gt;
Also, Nasal scripts that are loaded from $FG_ROOT/Nasal are automatically placed inside a namespace that is based on the script's name.&lt;br /&gt;
&lt;br /&gt;
For example, referring to our earlier &amp;quot;Hello World&amp;quot; example, global variables defined in the hello.nas script would be accessible by using &amp;quot;hello&amp;quot; as prefix from other modules:&lt;br /&gt;
&lt;br /&gt;
 # hello.nas&lt;br /&gt;
 var greeting=&amp;quot;Hello World&amp;quot;; # define a greeting symbol inside the hello namespace&lt;br /&gt;
&lt;br /&gt;
If you were now to read out the value from the greeting variable from another Nasal module, you would have to use the hello prefix:&lt;br /&gt;
&lt;br /&gt;
 # greetme.nas&lt;br /&gt;
 print(hello.greeting); # the hello prefix is referring to the hello namespace (or module).&lt;br /&gt;
&lt;br /&gt;
==Namespaces==&lt;br /&gt;
The Nasal Console built into FlightGear is quite handy when it comes to debugging code. However, here the namespaces need to be considered. In addition, Nasal sub modules (see above) have some special rules, too - basically, all Nasal files part of a &amp;quot;sub module&amp;quot; share a single name space based on the folder's name rather than the name of the individual Nasal files.&lt;br /&gt;
&lt;br /&gt;
For cases of Nasal code specific for an aircraft (like instruments, for example), the corresponding scripts could be loaded through the aircraft's &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file by putting it into the &amp;lt;tt&amp;gt;&amp;lt;nasal&amp;gt;...&amp;lt;/nasal&amp;gt;&amp;lt;tt&amp;gt; section&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nasal&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;lt;moduleA&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file1.nas&amp;lt;/file&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file2.nas&amp;lt;/file&amp;gt;		&lt;br /&gt;
    &amp;lt;/moduleA&amp;gt;&lt;br /&gt;
    &amp;lt;moduleB&amp;gt;&lt;br /&gt;
      &amp;lt;file&amp;gt;path/to/file3.nas&amp;lt;/file&amp;gt;	&lt;br /&gt;
    &amp;lt;/moduleB&amp;gt;&lt;br /&gt;
  &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, variables in files &amp;lt;tt&amp;gt;path/to/file1.nas&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;path/to/file2.nas&amp;lt;/tt&amp;gt; can be used in the Nasal console as&lt;br /&gt;
&lt;br /&gt;
  moduleA.varName;&lt;br /&gt;
&lt;br /&gt;
Variables in &amp;lt;tt&amp;gt;path/to/file3.nas&amp;lt;/tt&amp;gt; can be accessed as&lt;br /&gt;
&lt;br /&gt;
  moduleB.varName;&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal sub modules (i.e. files loaded and run from their own Nasal sub directory), are subject to some special rules, as all Nasal source files are automatically loaded into the same namespace, which is by default based on the sub module's folder name.&lt;br /&gt;
&lt;br /&gt;
More information can be found by clicking [http://wiki.flightgear.org/Namespaces_and_Methods here].&lt;br /&gt;
&lt;br /&gt;
== Variables - Advanced Uses ==&lt;br /&gt;
&lt;br /&gt;
Nasal, also supports Multi-assignment expressions. You can assign more than one variable (or lvalue) at a time by putting them in a parenthesized list:&lt;br /&gt;
&lt;br /&gt;
   (var a, var b) = (1, 2);&lt;br /&gt;
   var (a, b) = (1, 2);               # Shorthand for (var a, var b)&lt;br /&gt;
   (var a, v[0], obj.field) = (1,2,3) # Any assignable lvalue works&lt;br /&gt;
   var color = [1, 1, 0.5];&lt;br /&gt;
   var (r, g, b) = color;  # works with runtime vectors too&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vectors (lists or arrays) can be created from others using an ordered list of indexes and ranges. &lt;br /&gt;
This is usually called &amp;quot;vector slicing&amp;quot;.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
   var v1 = [&amp;quot;a&amp;quot;,&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   # &lt;br /&gt;
   var v2 = v1[3,2];   # == [&amp;quot;d&amp;quot;,&amp;quot;c&amp;quot;];&lt;br /&gt;
   var v3 = v1[1:3];   # i.e. range from 1 to 3: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;];&lt;br /&gt;
   var v4 = v1[1:];    # no value means &amp;quot;to the end&amp;quot;: [&amp;quot;b&amp;quot;,&amp;quot;c&amp;quot;,&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
   var i = 2;&lt;br /&gt;
   var v5 = v1[i];     # runtime expressions are fine: [&amp;quot;c&amp;quot;]&lt;br /&gt;
   var v6 = v1[-2,-1]; # negative indexes are relative to end: [&amp;quot;d&amp;quot;,&amp;quot;e&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
The range values can be computed at runtime (e.g. i=1; v5=v1[i:]). Negative indices work the same way they do with the vector functions (-1 is the last element, -2 is 2nd to last, etc...).&lt;br /&gt;
&lt;br /&gt;
== Storage: property tree vs. Nasal ==&lt;br /&gt;
With FlightGear's built-in property tree and Nasal's support for it, there are two obvious, and two somewhat competing, ways for storing scalar data: native Nasal variables and FlightGear properties, both of which can be easily accessed and managed from Nasal.&lt;br /&gt;
&lt;br /&gt;
The advantage to native Nasal-space data is that it's fast and simple.  If the only thing that will care about the value is your script, they are good choices.&lt;br /&gt;
&lt;br /&gt;
The property tree is an inter-subsystem communication thing.  This is what you want if you want to share data with the C++ world (for example, YASim &amp;lt;control-output&amp;gt; tags write to properties -- they don't understand Nasal), or read in via configuration files.&lt;br /&gt;
&lt;br /&gt;
Also, native Nasal data structures are usually far faster than their equivalent in property tree space.  This is because there are several layers of indirection in retrieving a property tree value. &lt;br /&gt;
&lt;br /&gt;
In general, this means that you shouldn't make overly excessive use of the property tree for storing state that isn't otherwise relevant to FlightGear or any of its subsystems. Doing that would in fact have adverse effects on the performance of your code. In general, you should favor Nasal variables and data structures and should only make use of properties to interface with the rest of FlightGear, or to easily provide debugging information at run time.&lt;br /&gt;
&lt;br /&gt;
As of FG 2.4.0, retrieving a value from the property tree via getprop is about 50% slower than accessing a native Nasal variable, and accessing the value via node.getValue() is 10-20% slower yet. This is an insignificant amount of time if you are retrieving and storing a few individual values from the property tree, but adds up fast if you are storing or retrieving hashes or large amounts of data.  (You can easily benchmark times on your own code using systime() or debug.benchmark.)&lt;br /&gt;
&lt;br /&gt;
In addition, it is worth noting that the Nasal/FlightGear APIs cannot currently be considered to be thread safe, this mean that -at least for now- the explicit use of pure Nasal space variables is the only way to exploit possible parallelism in your code by making use of threads.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== What is a function ? ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;function&amp;quot; is a piece of code that can be easily used repeatedly (without repeating the same code over and over again), this is achieved by associating a symbolic name with the piece of code, such as &amp;quot;print&amp;quot;, &amp;quot;show&amp;quot; or &amp;quot;get&amp;quot; for example. Whenever this symbolic name is then used in the program, the program will &amp;quot;jump&amp;quot; to the definition of the function and start running it, once the called function has completed it will automatically return to the instruction following the call.&lt;br /&gt;
&lt;br /&gt;
By using so called &amp;quot;function arguments&amp;quot; (see below) it is possible to parametrize a function (using variables) so that it may use data that is specific to each invocation.&lt;br /&gt;
&lt;br /&gt;
As previously shown, Nasal functions are implemented using the func keyword, The following snippet of code defines a new function named &amp;quot;log_message&amp;quot; with an empty function body (the curly braces).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}&lt;br /&gt;
&lt;br /&gt;
=== Function bodies ===&lt;br /&gt;
&lt;br /&gt;
To add a function body, you need to add code in between these curly braces.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous function arguments ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, arguments are by default passed in the &amp;quot;arg&amp;quot; array, not unlike perl. To understand how this works, you should probably first read up on Nasal vectors.&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note that this is equivalent to:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func() {&lt;br /&gt;
    print(arg[0]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In other words, the argument list &amp;quot;()&amp;quot; can be omitted if it is empty.&lt;br /&gt;
However, if you are new to Nasal or programming in general, it is probably a good idea to ALWAYS use parentheses, i.e. also for functions with empty argument lists - that makes it easy to get used to the syntax.&lt;br /&gt;
&lt;br /&gt;
Note that this is just an assignment of an (anonymous) function argument to the local &amp;quot;log_message&amp;quot; variable. There is no function declaration syntax in Nasal.&lt;br /&gt;
&lt;br /&gt;
Also, Nasal being a functional programming language, all passed arguments will be local to the corresponding scope. If you want to modify state in a function, you'll preferably return new state to the caller.&lt;br /&gt;
&lt;br /&gt;
===Named function arguments===&lt;br /&gt;
You can also pass named arguments to a function, thus saving the typing and performance costs of extracting them from the arg array:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The list of function arguments is called a function's &amp;quot;signature&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Default values for function arguments ===&lt;br /&gt;
&lt;br /&gt;
Function arguments can have default values, as in C++. Note that the default value must be a scalar (number, string, function, nil) and not a mutable composite object (list, hash).&lt;br /&gt;
&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;) {&lt;br /&gt;
    print(msg);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If some arguments have default values and some do not, those with default values must come first in the argument list:&lt;br /&gt;
&lt;br /&gt;
 #Incorrect:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, line, object=&amp;quot;ground&amp;quot;) { #some code }&lt;br /&gt;
&lt;br /&gt;
 #Correct:&lt;br /&gt;
 var log_message = func(msg=&amp;quot;error&amp;quot;, object=&amp;quot;ground&amp;quot;, line) { #some code }&lt;br /&gt;
&lt;br /&gt;
Any extra arguments after the named list are placed in the &amp;quot;arg&amp;quot; vector as above. You can rename this to something other than &amp;quot;arg&amp;quot; by specifying a final argument name with an ellipsis:&lt;br /&gt;
&lt;br /&gt;
 listify = func(elements...) { return elements; }&lt;br /&gt;
 listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]&lt;br /&gt;
&lt;br /&gt;
=== Returning from functions ===&lt;br /&gt;
&lt;br /&gt;
In Nasal, functions return implicitly the values of the last expression (i.e. &amp;quot;nil&amp;quot; in empty function bodies), you can also add an explicit &amp;quot;return&amp;quot; statement, for example to leave a function early. In addition, it is possible to return values, too.&lt;br /&gt;
&lt;br /&gt;
So, semantically, the previous snippet of code is equivalent to these:&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {return;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {nil;}&lt;br /&gt;
&lt;br /&gt;
 var log_message = func {}; &lt;br /&gt;
&lt;br /&gt;
 var log_message = func return;&lt;br /&gt;
&lt;br /&gt;
 var log_message = func nil;&lt;br /&gt;
&lt;br /&gt;
===Named arguments in function calls===&lt;br /&gt;
Nasal supports named function arguments in function calls, too.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the comma-separated list of ''positional'' function arguments, you can specify a hash literal in place of ordered function arguments, and it will become the local variable namespace for the called function, with variables named according to the hash indexes and with values according to the hash values.  This makes functions with many arguments more readable. &lt;br /&gt;
&lt;br /&gt;
And it also makes it possible to call function's without having to take care of the right order of passing arguments.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
 #if we have functions defined:&lt;br /&gt;
 var log_message = func (msg=&amp;quot;&amp;quot;) { #some code to log variable msg }&lt;br /&gt;
 var lookat =  func (heading=0, pitch=0, roll=0, x=nil, y=nil, z=nil, time=hil, fov=20) { #some code using those variables }&lt;br /&gt;
&lt;br /&gt;
 #we can use them them the usual way with comma separated list of arguments:&lt;br /&gt;
 log_message(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat (180, 20, 0, XO, YO, ZO, now, 55);&lt;br /&gt;
&lt;br /&gt;
 #or we can use the hash literal arguments instead:&lt;br /&gt;
 log_message(msg:&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
 lookat(heading:180, pitch:20, roll:0, x:X0, y:Y0, z:Z0,time:now, fov:55);&lt;br /&gt;
&lt;br /&gt;
Both methods for calling the functions above are equivalent, but note the the second method is more readable, less prone to error, and self-documenting in the code for the function call.&lt;br /&gt;
&lt;br /&gt;
As another example, consider:&lt;br /&gt;
&lt;br /&gt;
 var setPosition = func (latitude_deg, longitude_deg, altitude_ft) {&lt;br /&gt;
  # do something here &lt;br /&gt;
 }&lt;br /&gt;
 # the actual function call:&lt;br /&gt;
 setPosition( latitude_deg:34.00, longitude_deg:7.00, alt_ft:10000);&lt;br /&gt;
&lt;br /&gt;
In other words, such function calls become much more self-explanatory because everybody can see immediately what a value is doing.&lt;br /&gt;
This is a good practice, as you may eventually have to take a longer break, away from your code - and then even you yourself will come to appreciate such small things that make code more intuitive to work with.&lt;br /&gt;
&lt;br /&gt;
Declared arguments are checked and defaulted as would be expected: it's an error if you fail to pass a value for an undefaulted argument, missing default arguments get assigned as usual, and any rest parameter (e.g. &amp;quot;func(a,b=2,rest...){}&amp;quot;) will be assigned with an empty vector.&lt;br /&gt;
&lt;br /&gt;
===Nested functions, implicit return ===&lt;br /&gt;
Also, Nasal functions can be easily nested, for example:&lt;br /&gt;
&lt;br /&gt;
  var calculate = func(param1,param2,operator) {&lt;br /&gt;
   var add = func(p1,p2) {p1+p2;}&lt;br /&gt;
   var sub = func(p1,p2) {p1-p2;}&lt;br /&gt;
   var mul = func(p1,p2) {p1*p2;}&lt;br /&gt;
   var div = func(p1,p2) {p1/p2;}&lt;br /&gt;
   if (operator==&amp;quot;+&amp;quot;) return add(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;-&amp;quot;) return sub(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;*&amp;quot;) return mul(param1,param2);&lt;br /&gt;
   if (operator==&amp;quot;/&amp;quot;) return div(param1,param2);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Note that the add,sub,mul and div functions in this example do not make use of an explicit return statement, instead the result of each expression is implicitly returned to the caller.&lt;br /&gt;
&lt;br /&gt;
Nasal functions that just consist of such simple expressions can also be further simplified to read:&lt;br /&gt;
&lt;br /&gt;
  var add = func(val1,val2) val1+val2;&lt;br /&gt;
&lt;br /&gt;
=== Function overloading ===&lt;br /&gt;
&lt;br /&gt;
Note that Nasal functions can generally not be [[http://en.wikipedia.org/wiki/Function_overloading overloaded]], and that operator overloading in particular is also not supported.&lt;br /&gt;
&lt;br /&gt;
However, the effects of '''function overloading''' can obviously be implemented individually by each function, simply by processing the number and type of passed arguments at the start of the function body. The FlightGear code base contains a number of examples for this, i.e. it is for example possible to pass properties in the form of plain strings to a callback or in the form of a Nasal wrapper like props.Node.&lt;br /&gt;
&lt;br /&gt;
So this can be accomplished by first checking the argument count and then the types of arguments passed to the function.&lt;br /&gt;
&lt;br /&gt;
To provide an example, here's a simple function to multiply two numbers, no matter if they are provided as scalars, as a vector or as x/y members of a hash:&lt;br /&gt;
&lt;br /&gt;
 var multiply2 = func (params) {&lt;br /&gt;
  if (typeof(params)==&amp;quot;scalar&amp;quot;) return params*arg[0];&lt;br /&gt;
  if (typeof(params)==&amp;quot;vector&amp;quot;) return params[0]*params[1];&lt;br /&gt;
  if (typeof(params)==&amp;quot;hash&amp;quot;)   return params.x*params.y;&lt;br /&gt;
  die(&amp;quot;cannot do what you want me to do&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
So, now you have a very simple form of an &amp;quot;overloaded&amp;quot; function that supports different argument types and numbers:&lt;br /&gt;
&lt;br /&gt;
 multiply2(  2,6); # multiply two scalars&lt;br /&gt;
 multiply2( [5,7] ); # multiply two scalars stored in a vector&lt;br /&gt;
 multiply2( {x:8, y:9} ); # multiply two scalars stored in a hash&lt;br /&gt;
&lt;br /&gt;
You could obviously extend this easily to support an arbitrary number of arguments by just using a for loop here.&lt;br /&gt;
&lt;br /&gt;
As you can see, the basic idea is pretty simple and also scalable, you could easily extend this to and also return different types of values, such as vectors or hashes. This could for example be used to create wrappers in Nasal space for doing 3D maths, with vectors and matrices, so that a matrix multiplication could return a new matrix, too.&lt;br /&gt;
&lt;br /&gt;
===Functional programming, higher order functions, generators;===&lt;br /&gt;
As previously mentioned, arguments to a Nasal function can also be functions themselves (Nasal being a functional programming language), this means that Nasal functions are higher order functions so that you can easily pass and return functions to and from Nasal functions. This can for example be used to dynamically create new functions (such functions are commonly called 'generators'):&lt;br /&gt;
&lt;br /&gt;
  # a function that returns a new custom function&lt;br /&gt;
  var i18n_hello = func(hello) {&lt;br /&gt;
   return func(name) { # returns an anonymous/unnamed function&lt;br /&gt;
     print(hello,name);&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  # create three new functions&lt;br /&gt;
  var english_hello = i18n_hello(&amp;quot;Good Day &amp;quot;);&lt;br /&gt;
  var spanish_hello = i18n_hello(&amp;quot;Buenos Dias &amp;quot;);&lt;br /&gt;
  var italian_hello = i18n_hello(&amp;quot;Buon giorno &amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  # actually call these functions&lt;br /&gt;
  english_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  spanish_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
  italian_hello(&amp;quot;FlightGear&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== Using helper functions ===&lt;br /&gt;
&lt;br /&gt;
It is possible to simplify complex function calls by introducing small helper functions, for example consider:&lt;br /&gt;
&lt;br /&gt;
 var l = thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, you could just as well create a small helper function named&amp;quot;thermalLift.new_from_ev(ev)&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
  thermalLift.new_from_ev = func (ev) {&lt;br /&gt;
   thermalLift.new(ev.lat, ev.lon, ev.radius, ev.height, ev.cn, ev.sh, ev.max_lift, ev.f_lift_radius);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 var l=thermalLift.new_from_ev(ev);&lt;br /&gt;
&lt;br /&gt;
Note that the expression to invoke your code would then also become less complicated and much more comprehensible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you have expressions of nested method calls, such as:&lt;br /&gt;
&lt;br /&gt;
    t.getNode(&amp;quot;latitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;latitude-deg&amp;quot;).getValue());&lt;br /&gt;
    t.getNode(&amp;quot;longitude-deg&amp;quot;).setValue(f.getNode(&amp;quot;longitude-deg&amp;quot;).getValue());&lt;br /&gt;
&lt;br /&gt;
You could just as easily introduce a small helper function to wrap the code, that would be less typing for you, less code to read (and understand) for others and generally it would help localize functionality (and possible errors):&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(t,f,path) t.getNode(path).setValue(f.getNode(path).getValue());&lt;br /&gt;
&lt;br /&gt;
So you would simply take the complex expression and generalize it by adding variables that you pass in from a function object, then you could simply call your new function like this:&lt;br /&gt;
&lt;br /&gt;
    copyNode(t,f,&amp;quot;latitude-deg&amp;quot;);&lt;br /&gt;
    copyNode(t,f,&amp;quot;longitude-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    foreach(var p; [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;,&amp;quot;generated-flag&amp;quot;])&lt;br /&gt;
      copyNode(t,f,p);&lt;br /&gt;
&lt;br /&gt;
or as a complete function accepting a vector of properties:&lt;br /&gt;
&lt;br /&gt;
    var copyNode = func(target,source,properties) { &lt;br /&gt;
     if (typeof(properties)!=&amp;quot;vector&amp;quot;) properties=[properties];&lt;br /&gt;
     if (typeof(target)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(target);&lt;br /&gt;
     if (typeof(source)!=&amp;quot;hash&amp;quot;) target=props.globals.getNode(source)&lt;br /&gt;
     foreach(var path; properties)&lt;br /&gt;
      target.getNode(path).setValue( source.getNode(path).getValue() );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copyNode(&amp;quot;/temp/test&amp;quot;, &amp;quot;/position&amp;quot;, [&amp;quot;latitude-deg&amp;quot;, &amp;quot;longitude-deg&amp;quot;, &amp;quot;altitude-ft&amp;quot;]);&lt;br /&gt;
&lt;br /&gt;
Whenever you have very similar lines of code that seem fairly repetitive, it is a good idea to consider introducing small helper functions. You can use plenty of small helper functions and then just &amp;quot;chain&amp;quot; them together, rather than using complex nested expressions that make your head spin.&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Nasal has no &amp;quot;statements&amp;quot;, which means that any expression can appear in any context. This means that you can use an if/else clause to do what the ?: does in C. &lt;br /&gt;
The last semicolon in a code block is optional, to make this prettier&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { if(n&amp;lt;0) { -n } else { n } }&lt;br /&gt;
&lt;br /&gt;
But for those who don't like typing, the ternary operator works like you expect:&lt;br /&gt;
&lt;br /&gt;
 abs = func(n) { n &amp;lt; 0 ? -n : n }&lt;br /&gt;
&lt;br /&gt;
In addition, Nasal supports braceless blocks, like they're known from C/C++ and other languages:&lt;br /&gt;
&lt;br /&gt;
 var foo=1;&lt;br /&gt;
 if (foo)&lt;br /&gt;
   print(&amp;quot;1\n&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
   print(&amp;quot;0\n&amp;quot;);&lt;br /&gt;
 print(&amp;quot;this is printed regardless\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Instead of a switch statement one can use&lt;br /&gt;
&lt;br /&gt;
  if (1==2) {&lt;br /&gt;
    print(&amp;quot;wrong&amp;quot;);&lt;br /&gt;
  } else if (1==3) { # NOTE the space between else and if&lt;br /&gt;
    print(&amp;quot;wronger&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;don't know&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
which produces the expected output of &amp;lt;code&amp;gt;don't know&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; logic is actually quite logical, let's just restate the obvious:&lt;br /&gt;
&lt;br /&gt;
  if (nil) {&lt;br /&gt;
    print(&amp;quot;This should never be printed&amp;quot;);&lt;br /&gt;
  } else {&lt;br /&gt;
    print(&amp;quot;This will be printed, because nil is always false&amp;quot;);		&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nasal's binary boolean operators are &amp;quot;and&amp;quot; and &amp;quot;or&amp;quot;, unlike C. unary not is still &amp;quot;!&amp;quot; however. &lt;br /&gt;
They short-circuit like you expect&lt;br /&gt;
&lt;br /&gt;
 var toggle = 0;&lt;br /&gt;
 var a = nil;&lt;br /&gt;
 if(a and a.field == 42) {&lt;br /&gt;
    toggle = !toggle; # doesn't crash when a is nil&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can easily reduce the complexity of huge conditional (IF) statements, such as this one:&lt;br /&gt;
&lt;br /&gt;
    if (a==1) function_a();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==2) function_b();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==3) function_c();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==4) function_d();&lt;br /&gt;
    else&lt;br /&gt;
    if (a==5) function_e();&lt;br /&gt;
&lt;br /&gt;
.. just by using the variable as a key (index) into a hash, so that you can directly call the corresponding function:&lt;br /&gt;
&lt;br /&gt;
    var mapping = {1:function_a, 2:function_b, 3:function_c, 4:function_d,5:function_e};&lt;br /&gt;
    mapping[a] ();&lt;br /&gt;
&lt;br /&gt;
This initializes first a hash map of values and maps a function &amp;quot;pointer&amp;quot; to each value, so that accessing mapping[x] will return the function pointer for the key &amp;quot;x&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Next, you can actually call the function by appending a list of function arguments (empty parentheses for no args) to the hash lookup.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can reduce the complexity of huge conditional blocks. For example, consider:&lt;br /&gt;
&lt;br /&gt;
    # weather_tile_management.nas&lt;br /&gt;
    460         if (code == &amp;quot;altocumulus_sky&amp;quot;){weather_tiles.set_altocumulus_tile();}&lt;br /&gt;
    461         else if (code == &amp;quot;broken_layers&amp;quot;) {weather_tiles.set_broken_layers_tile();}&lt;br /&gt;
    462         else if (code == &amp;quot;stratus&amp;quot;) {weather_tiles.set_overcast_stratus_tile();}&lt;br /&gt;
    463         else if (code == &amp;quot;cumulus_sky&amp;quot;) {weather_tiles.set_fair_weather_tile();}&lt;br /&gt;
    464         else if (code == &amp;quot;gliders_sky&amp;quot;) {weather_tiles.set_gliders_sky_tile();}&lt;br /&gt;
    465         else if (code == &amp;quot;blue_thermals&amp;quot;) {weather_tiles.set_blue_thermals_tile();}&lt;br /&gt;
    466         else if (code == &amp;quot;summer_rain&amp;quot;) {weather_tiles.set_summer_rain_tile();}&lt;br /&gt;
    467         else if (code == &amp;quot;high_pressure_core&amp;quot;) {weather_tiles.set_high_pressure_core_tile();}&lt;br /&gt;
    468         else if (code == &amp;quot;high_pressure&amp;quot;) {weather_tiles.set_high_pressure_tile();}&lt;br /&gt;
    469         else if (code == &amp;quot;high_pressure_border&amp;quot;) {weather_tiles.set_high_pressure_border_tile();}&lt;br /&gt;
    470         else if (code == &amp;quot;low_pressure_border&amp;quot;) {weather_tiles.set_low_pressure_border_tile();}&lt;br /&gt;
    471         else if (code == &amp;quot;low_pressure&amp;quot;) {weather_tiles.set_low_pressure_tile();}&lt;br /&gt;
    472         else if (code == &amp;quot;low_pressure_core&amp;quot;) {weather_tiles.set_low_pressure_core_tile();}&lt;br /&gt;
    473         else if (code == &amp;quot;cold_sector&amp;quot;) {weather_tiles.set_cold_sector_tile();}&lt;br /&gt;
    474         else if (code == &amp;quot;warm_sector&amp;quot;) {weather_tiles.set_warm_sector_tile();}&lt;br /&gt;
    475         else if (code == &amp;quot;tropical_weather&amp;quot;) {weather_tiles.set_tropical_weather_tile();}&lt;br /&gt;
    476         else if (code == &amp;quot;test&amp;quot;) {weather_tiles.set_4_8_stratus_tile();}&lt;br /&gt;
    477         else ...&lt;br /&gt;
&lt;br /&gt;
While this is not a very complex or huge block of code, it is an excellent example for very good naming conventions used already, because the consistency of naming variables and functions can pay off easily here, with just some very small changes, you can already reduce the whole thing to a hash lookup like this:&lt;br /&gt;
&lt;br /&gt;
  weather_tiles[&amp;quot;set_&amp;quot;~code~&amp;quot;_tile&amp;quot;]();  # naming convention&lt;br /&gt;
&lt;br /&gt;
This would dynamically concatenate a key consisting of &amp;quot;set_&amp;quot; + code + &amp;quot;_title&amp;quot; into the hash named weather_tiles, and then call the function that is returned from the hash lookup.&lt;br /&gt;
&lt;br /&gt;
So for this to work you only need to enforce consistency when naming your functions (i.e. this would of course CURRENTLY fail when the variable code contains &amp;quot;test&amp;quot; because there is no such hash member (it's &amp;quot;4_8_stratus&amp;quot; instead).&lt;br /&gt;
&lt;br /&gt;
The same applies to cumulus sky (fair weather), stratus/overcast stratus.&lt;br /&gt;
&lt;br /&gt;
But these are very simple changes to do (just renaming these functions to match the existing conventions). When you do that, you can easily replace such huge IF statements and replace them with a single hash lookup and function call:&lt;br /&gt;
&lt;br /&gt;
 hash[key] (arguments...);&lt;br /&gt;
&lt;br /&gt;
For example, consider:&lt;br /&gt;
&lt;br /&gt;
 var makeFuncString = func(c) return tolower(&amp;quot;set_&amp;quot;~c~&amp;quot;_tile&amp;quot;);&lt;br /&gt;
 var isFunc = func(f) typeof(f)=='func';&lt;br /&gt;
 var hasMethod = func(h,m) contains(h,m) and isFunc;&lt;br /&gt;
 var callIfAvailable = func(hash, method, unavailable=func{} ) {&lt;br /&gt;
  var c=hasMethod(hash,makeFuncString(m) ) or unavailable();&lt;br /&gt;
  hash[makeFuncString(m)] ();&lt;br /&gt;
 }&lt;br /&gt;
 callIfAvailable( weather_tiles,code, func {die(&amp;quot;key not found in hash or not a func&amp;quot;);} );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Initializing data structures ==&lt;br /&gt;
&lt;br /&gt;
There are some more possibilities to increase the density of your code, such as by removing redundant code or by generalizing and refactoring existing code so that it can be reused in different places (i.e. avoiding duplicate code): &lt;br /&gt;
&lt;br /&gt;
For example see weather_tile_management.nas #1000 (create_neighbours function):&lt;br /&gt;
&lt;br /&gt;
    1008 x = -40000.0; y = 40000.0;&lt;br /&gt;
    1009 setprop(lw~&amp;quot;tiles/tile[0]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1010 setprop(lw~&amp;quot;tiles/tile[0]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1011 setprop(lw~&amp;quot;tiles/tile[0]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1012 setprop(lw~&amp;quot;tiles/tile[0]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1013 setprop(lw~&amp;quot;tiles/tile[0]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1014 setprop(lw~&amp;quot;tiles/tile[0]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1015 setprop(lw~&amp;quot;tiles/tile[0]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1016&lt;br /&gt;
    1017 x = 0.0; y = 40000.0;&lt;br /&gt;
    1018 setprop(lw~&amp;quot;tiles/tile[1]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1019 setprop(lw~&amp;quot;tiles/tile[1]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1020 setprop(lw~&amp;quot;tiles/tile[1]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1021 setprop(lw~&amp;quot;tiles/tile[1]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1022 setprop(lw~&amp;quot;tiles/tile[1]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1023 setprop(lw~&amp;quot;tiles/tile[1]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1024 setprop(lw~&amp;quot;tiles/tile[1]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1025&lt;br /&gt;
    1026 x = 40000.0; y = 40000.0;&lt;br /&gt;
    1027 setprop(lw~&amp;quot;tiles/tile[2]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1028 setprop(lw~&amp;quot;tiles/tile[2]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1029 setprop(lw~&amp;quot;tiles/tile[2]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1030 setprop(lw~&amp;quot;tiles/tile[2]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1031 setprop(lw~&amp;quot;tiles/tile[2]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1032 setprop(lw~&amp;quot;tiles/tile[2]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1033 setprop(lw~&amp;quot;tiles/tile[2]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1034&lt;br /&gt;
    1035 x = -40000.0; y = 0.0;&lt;br /&gt;
    1036 setprop(lw~&amp;quot;tiles/tile[3]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1037 setprop(lw~&amp;quot;tiles/tile[3]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1038 setprop(lw~&amp;quot;tiles/tile[3]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1039 setprop(lw~&amp;quot;tiles/tile[3]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1040 setprop(lw~&amp;quot;tiles/tile[3]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1041 setprop(lw~&amp;quot;tiles/tile[3]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1042 setprop(lw~&amp;quot;tiles/tile[3]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1043&lt;br /&gt;
    1044 # this is the current tile&lt;br /&gt;
    1045 x = 0.0; y = 0.0;&lt;br /&gt;
    1046 setprop(lw~&amp;quot;tiles/tile[4]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1047 setprop(lw~&amp;quot;tiles/tile[4]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1048 setprop(lw~&amp;quot;tiles/tile[4]/generated-flag&amp;quot;,1);&lt;br /&gt;
    1049 setprop(lw~&amp;quot;tiles/tile[4]/tile-index&amp;quot;,1);&lt;br /&gt;
    1050 setprop(lw~&amp;quot;tiles/tile[4]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1051 setprop(lw~&amp;quot;tiles/tile[4]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1052 setprop(lw~&amp;quot;tiles/tile[4]/orientation-deg&amp;quot;,getprop(lw~&amp;quot;tmp/tile-orientation-deg&amp;quot;));&lt;br /&gt;
    1053&lt;br /&gt;
    1054&lt;br /&gt;
    1055 x = 40000.0; y = 0.0;&lt;br /&gt;
    1056 setprop(lw~&amp;quot;tiles/tile[5]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1057 setprop(lw~&amp;quot;tiles/tile[5]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1058 setprop(lw~&amp;quot;tiles/tile[5]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1059 setprop(lw~&amp;quot;tiles/tile[5]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1060 setprop(lw~&amp;quot;tiles/tile[5]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1061 setprop(lw~&amp;quot;tiles/tile[5]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1062 setprop(lw~&amp;quot;tiles/tile[5]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1063&lt;br /&gt;
    1064 x = -40000.0; y = -40000.0;&lt;br /&gt;
    1065 setprop(lw~&amp;quot;tiles/tile[6]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1066 setprop(lw~&amp;quot;tiles/tile[6]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1067 setprop(lw~&amp;quot;tiles/tile[6]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1068 setprop(lw~&amp;quot;tiles/tile[6]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1069 setprop(lw~&amp;quot;tiles/tile[6]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1070 setprop(lw~&amp;quot;tiles/tile[6]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1071 setprop(lw~&amp;quot;tiles/tile[6]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1072&lt;br /&gt;
    1073 x = 0.0; y = -40000.0;&lt;br /&gt;
    1074 setprop(lw~&amp;quot;tiles/tile[7]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1075 setprop(lw~&amp;quot;tiles/tile[7]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1076 setprop(lw~&amp;quot;tiles/tile[7]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1077 setprop(lw~&amp;quot;tiles/tile[7]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1078 setprop(lw~&amp;quot;tiles/tile[7]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1079 setprop(lw~&amp;quot;tiles/tile[7]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1080 setprop(lw~&amp;quot;tiles/tile[7]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1081&lt;br /&gt;
    1082 x = 40000.0; y = -40000.0;&lt;br /&gt;
    1083 setprop(lw~&amp;quot;tiles/tile[8]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    1084 setprop(lw~&amp;quot;tiles/tile[8]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    1085 setprop(lw~&amp;quot;tiles/tile[8]/generated-flag&amp;quot;,0);&lt;br /&gt;
    1086 setprop(lw~&amp;quot;tiles/tile[8]/tile-index&amp;quot;,-1);&lt;br /&gt;
    1087 setprop(lw~&amp;quot;tiles/tile[8]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    1088 setprop(lw~&amp;quot;tiles/tile[8]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    1089 setprop(lw~&amp;quot;tiles/tile[8]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    1090 }&lt;br /&gt;
&lt;br /&gt;
At first glance, this seems like a fairly repetitive and redundant block of code, so it could probably be simplified easily:&lt;br /&gt;
&lt;br /&gt;
    var create_neighbours = func (blat, blon, alpha)        {&lt;br /&gt;
    var phi = alpha * math.pi/180.0;&lt;br /&gt;
    calc_geo(blat);&lt;br /&gt;
    var index=0;&lt;br /&gt;
    var pos = [  [-40000.0,40000.0], [0.0, 40.000], [40000.0, 40000.0], [-40000, 0],  [0,0], [40000,0], [-40000,-40000], [0,-40000], [40000,-40000] ];&lt;br /&gt;
    foreach (var p;pos) {&lt;br /&gt;
    x=p[0]; y=p[1];&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/latitude-deg&amp;quot;,blat + get_lat(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/longitude-deg&amp;quot;,blon + get_lon(x,y,phi));&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/generated-flag&amp;quot;,0);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/tile-index&amp;quot;,-1);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/code&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/timestamp-sec&amp;quot;,weather_dynamics.time_lw);&lt;br /&gt;
    setprop(lw~&amp;quot;tiles/tile[index]/orientation-deg&amp;quot;,alpha);&lt;br /&gt;
    index=index+1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration.&lt;br /&gt;
&lt;br /&gt;
===for, while, foreach, and forindex loops===&lt;br /&gt;
Nasal's looping constructs are mostly C-like:&lt;br /&gt;
&lt;br /&gt;
 for(var i=0; i &amp;lt; 3; i = i+1) {&lt;br /&gt;
  # loop body&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
 while (condition) {&lt;br /&gt;
 # loop body&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The differences are that there is no do{}while(); construct, and there is a foreach, which takes a local variable name as its first argument and a vector as its second:&lt;br /&gt;
&lt;br /&gt;
  foreach(elem; list1) { doSomething(elem); }  # NOTE: the delimiter is a SEMICOLON ;&lt;br /&gt;
&lt;br /&gt;
The hash/vector index expression is an lvalue that can be assigned as well as inspected:&lt;br /&gt;
&lt;br /&gt;
  foreach(light; lights) { lightNodes[light] = propertyPath; }&lt;br /&gt;
&lt;br /&gt;
To walk through all elements of a hash, for a foreach loop on the keys of they hash.  Then you call pull up the values of the hash using the key.  Example:&lt;br /&gt;
&lt;br /&gt;
 myhash= {first: 1000, second: 250, third: 25.2 };&lt;br /&gt;
 foreach (var i; keys (myhash)) {&lt;br /&gt;
   #multiply each value by 2:&lt;br /&gt;
   myhash[i] *= 2; &lt;br /&gt;
   #print the key and new value:&lt;br /&gt;
   print (i, &amp;quot;: &amp;quot;, myhash[i]);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;quot;forindex&amp;quot;, which is like foreach except that it assigns the index of each element, instead of the value, to the loop variable.&lt;br /&gt;
&lt;br /&gt;
 forindex(i; list1) { doSomething(list1[i]); }&lt;br /&gt;
&lt;br /&gt;
Also, braceless blocks work for loops equally well:&lt;br /&gt;
&lt;br /&gt;
 var c=0;&lt;br /&gt;
 while( c&amp;lt;5 )&lt;br /&gt;
  print( c+=1 );&lt;br /&gt;
 print(&amp;quot;end of loop\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===settimer loops===&lt;br /&gt;
Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. &lt;br /&gt;
&lt;br /&gt;
For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;) (though it is possible to make a function call return a function object--an advanced functional programming technique that you won't need to worry about if you're just getting started with Nasal). &lt;br /&gt;
&lt;br /&gt;
The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The built-in function keys() returns a vector with the keys of the hash.  The function values() returns a vector with the values of the hash. For example:&lt;br /&gt;
&lt;br /&gt;
  debug.dump (keys(airport)); #prints ['LOXZ', 'LOWI', 'LOXL']&lt;br /&gt;
  debug.dump (values (airport)); #prints ['Zeltweg', 'Innsbruck', 'Linz Hoersching'] &lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only half the truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
Please note that Nasal's currently supported form of encapsulation does not provide support for any form of data/information hiding (restricting access), i.e. all hash fields (but also all hash methods) are always publicly accessible (so there's nothing like the &amp;quot;private&amp;quot; or &amp;quot;protected&amp;quot; keywords in C++: in this sense, Nasal's inheritance mechanism can be thought of like C++ structs which are also public by default).&lt;br /&gt;
&lt;br /&gt;
The major difference being, that all members (functions and fields) are also always '''mutable''', which means that functions can modify the behavior of other functions quite easily, this also applies to the parents vector, too.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
&lt;br /&gt;
Finally, as you know now, Nasal, being a dynamic programming language, doesn't require or support any manual memory management, so unlike C++, you don't need to call operators like &amp;quot;new&amp;quot; or &amp;quot;delete&amp;quot; to allocate or free your memory.&lt;br /&gt;
&lt;br /&gt;
However, if you do know that you don't need a certain variable anymore, you can certainly give a hint to the built-in garbage collector to free it, by assigning a &amp;quot;nil&amp;quot; value to it. &lt;br /&gt;
&lt;br /&gt;
This can certainly pay off when using more complex data structures such as nested vectors or hashes, because it will tell the built-in garbage collector to remove all references to the corresponding symbols, so that they can be freed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to make use of Nasal's delete() function to remove a symbol from a namespace (hash).&lt;br /&gt;
&lt;br /&gt;
So, if you are concerned about your script's memory requirements, using a combination of setting symbols to nil, or deleting them as appropriate, would allow you to create helper functions for freeing data structures easily.&lt;br /&gt;
&lt;br /&gt;
In addition, it is probably worth noting that this is also the only way to sanely reset an active Nasal namespace or even the whole interpreter. You need to do this in order to reload or re-initialize your code without restarting the whole FlightGear session [[Nasal_scripting_language#Managing_timers_and_listeners]].&lt;br /&gt;
&lt;br /&gt;
Obviously, you should first of all ensure that there is no more code running, this includes any registered listeners or timers, but also any others loops or recursive functions.&lt;br /&gt;
&lt;br /&gt;
Thus, if you'd like to reload a Nasal source file at run time, you should disable all running code, and then reset the corresponding namespace, too. This is to ensure that you get a clean and consistent namespace.&lt;br /&gt;
&lt;br /&gt;
Nasal provides a number of core library functions to manipulate namespaces, such as:&lt;br /&gt;
&lt;br /&gt;
* caller() - to get a strack trace of active functions currently on the Nasal stack&lt;br /&gt;
* compile() - to compile new Nasal code &amp;quot;on the fly&amp;quot;, i.e. dynamically from a string&lt;br /&gt;
* closure() - to query the lexical namespace of active functions&lt;br /&gt;
* bind() - to create new function objects&lt;br /&gt;
&lt;br /&gt;
More information is available here: http://www.plausible.org/nasal/lib.html&lt;br /&gt;
&lt;br /&gt;
If, on the other hand, you are using these data structures in some repeated fashion, it might make sense to keep the data structure itself around and simply re-use it next time (overwriting data as required), instead of always allocating/creating a new one, this is called &amp;quot;caching&amp;quot; and can pay off from a performance perspective.&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value (this is usually called &amp;quot;method chaining&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message (this can be compared to the throw() mechanism in C++).&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. &lt;br /&gt;
&lt;br /&gt;
===setlistener() vs. _setlistener() ===&lt;br /&gt;
You are requested *not* to use the raw _setlistener() function, except in files in $FG_ROOT/Nasal/ when they are&lt;br /&gt;
needed immediately. Only then the raw function is required, as it doesn't rely on props.nas.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;tt&amp;gt;When listeners don't work&amp;lt;/tt&amp;gt;===&lt;br /&gt;
Unfortunately, '''listeners don't work on so-called &amp;quot;tied&amp;quot; properties''' when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Examples of properties where setlistener ''won't'' work: &lt;br /&gt;
&lt;br /&gt;
* /position/elevation-ft&lt;br /&gt;
* /ai/models/aircraft/orientation/heading-deg&lt;br /&gt;
* Any property node created as an alias&lt;br /&gt;
* Lots of others&lt;br /&gt;
&lt;br /&gt;
Before working to create a listener, always check whether a listener will work with that property node by control-clicking the &amp;quot;.&amp;quot; in property browser to put it into verbose mode, and then checking whether the property node for which you want to set up a listener is marked with a &amp;quot;T&amp;quot; or not.&lt;br /&gt;
&lt;br /&gt;
If you can't set a listener for a particular property, the alternative is to use settimer to set up a timer loop that checks the property value regularly. &lt;br /&gt;
&lt;br /&gt;
Listeners are most efficient for properties that change only occasionally.  No code is called at all during frames where the listener function is not called.  If the property value changes every frame, setting up a settimer loop with time=0 will execute every frame, just the same as setlistener would, and the settimer loop is more efficient than setting a listener. This is one reason the fact the setlistener doesn't work on certain tied and FDM properties is not a great loss.  See the section on timer loops below.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. &lt;br /&gt;
&lt;br /&gt;
If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This is important for cases where a property is written to once per frame, no matter if the value changed or not. YASim, for example, does that for /gear/gear/wow or /gear/launchbar/state.&lt;br /&gt;
So, this should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
For both optional flags 0 means less calls, and 1 means more calls. The first is for startup behavior, and the second for runtime behavior.&lt;br /&gt;
&lt;br /&gt;
Here's a real-life example:&lt;br /&gt;
&lt;br /&gt;
  setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
YASim writes once per frame the string &amp;quot;Disengaged&amp;quot; to property /gear/launchbar/state. When an aircraft on deck of the aircraft carrier locks into the catapult, this changes to &amp;quot;Engaged&amp;quot;, which is then written again in every frame, until the aircraft leaves the catapult. Because the locking in is a bit difficult -- one has to target the sensitive area quite exactly --, it was desirable to get some quick feedback: a screen message that's also spoken by the Festival speech synthesis. With the args 1 and 0, this is done initially (for the unlikely case that we are locked in from the beginning), and then only when the node changes from an arbitrary value to &amp;quot;Engaged&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
If you have set a callback function named ''myCallbackFunc'' via &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; (''setlistener(myNode, myCallbackFunc)''), you can use this syntax in the callback function:&lt;br /&gt;
&lt;br /&gt;
 myCallbackFunc ([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success, &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
Callback functions can, optionally, access up to four parameters which are handed over via regular function arguments. Many times none of these parameters is used at all, as in the above example.&lt;br /&gt;
&lt;br /&gt;
Most often, only the first parameter is used--which gives the node of the changed value.&lt;br /&gt;
&lt;br /&gt;
The following code attaches the monitor_course() function to a gps property, using the argument ''course'' to get the node with the changed value.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
Here is code that accesses two arguments--the changed node and the listened-to node (these may be different when monitoring all children of a certain node)--and also shows how to monitor changes to a node including changes to children:&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course, flightinfo) {&lt;br /&gt;
     print(&amp;quot;One way to get the course setting: &amp;quot;, flightinfo.leg-course-deviation-deg.getValue());&lt;br /&gt;
     print(&amp;quot;Another way to get the same setting &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp&amp;quot;, monitor_course, 0, 2);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be an anonymous function made directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Beware, however, that the contents of a function defined within the &amp;lt;tt&amp;gt;setlistener&amp;lt;/tt&amp;gt; call are not evaluated until the call is actually made. If, for instance, local variables change before the setlistener call happens, the call will reflect the current value of those variables ''at the time the callback function is called'', not the value ''at the time the listener was set''. &lt;br /&gt;
&lt;br /&gt;
For example, with this loop, the function will always return the value 10--even if mynode[1], mynode[2], mynode[3] or any of the others is the one that changed. It is because the contents of the setlistener are evaluated after the loop has completed running and at that point, i=10:&lt;br /&gt;
&lt;br /&gt;
 var output = func(number) {&lt;br /&gt;
     print(&amp;quot;mynode&amp;quot;, number, &amp;quot; has changed!&amp;quot;); #This won't work!&lt;br /&gt;
 }&lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func{ output (i); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
You can also access the four available function properties (or just one, two, or three of them as you need) in your anonymous function. Here is an example that accesses the first value:&lt;br /&gt;
 &lt;br /&gt;
 for(i=1; i &amp;lt;= 10; i = i+1) {&lt;br /&gt;
    var i = setlistener(&amp;quot;mynode[&amp;quot;~i~&amp;quot;]&amp;quot;, func (changedNode) { print (changedNode.getPath() ~ &amp;quot; : &amp;quot; ~ changedNode.getValue()); });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html] and [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see $FG_ROOT/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
  print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
      if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
          setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
  }, 1, 0);&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html]&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC) [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html].&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see $FG_ROOT/Docs/README.commands for a list of available commands: http://gitorious.org/fg/fgdata/blobs/master/Docs/README.commands&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, with a slash (/) inserted between each element. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; concatenates a list of input arguments by means of inserting a &amp;quot;/&amp;quot; in between. That is nice for properties, as this slash is part of the tree. However, when one wants to make use of indices, like [0], one has to concatenate by hand (using &amp;quot;~&amp;quot;) ''inside'' one part of the string argument list. An example is:&lt;br /&gt;
&lt;br /&gt;
  var i = 4;&lt;br /&gt;
  setprop(&amp;quot;instrumentation&amp;quot;,&amp;quot;cdu&amp;quot;,&amp;quot;page[&amp;quot;~i~&amp;quot;]&amp;quot;,&amp;quot;title&amp;quot;,&amp;quot;MENU&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
This results in instrumentation/cdu/page[4]/title = 'MENU' (string)&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; can be erased via&lt;br /&gt;
&lt;br /&gt;
  props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
  props.globals.getNode(&amp;quot;/foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
 settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
 myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
 myarg2=432;&lt;br /&gt;
 settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 # simulation time example&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
 # real time example&lt;br /&gt;
 var popdown = func ( tipArg ) { &lt;br /&gt;
  fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
    &lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
 &lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
 &lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Nasal_scripting_language#settimer_loops|More information about best practices for using the settimer function to create loops in Nasal is elsewhere on this page.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
  #benchmarking example:&lt;br /&gt;
  var start = systime();&lt;br /&gt;
  how_fast_am_I(123);&lt;br /&gt;
  var end = systime();&lt;br /&gt;
  print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://flightgear.org/forums/viewtopic.php?f=4&amp;amp;p=135044#p135044 discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
  var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
  var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
  var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
  { lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the&lt;br /&gt;
airport, and a hash with runways, each of which consists of lat/lon/&lt;br /&gt;
/length/width/heading/threshold[12]/stopway[12]. Only one side of each&lt;br /&gt;
runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
==Built-in functions==&lt;br /&gt;
&lt;br /&gt;
===sort(vector, function)===&lt;br /&gt;
Creates a new vector containing the elements in the input vector sorted in ascending order according to the rule given by function, which takes two arguments (elements of the input vector) and should return less than zero, zero, or greater than zero if the first argument is, respectively, less than, equal to, or greater than the second argument. Despite being implemented with ANSI C qsort(), the sort is stable; &amp;quot;equal&amp;quot; elements in the output vector will appear in the same relative order as they do in the input.&lt;br /&gt;
&lt;br /&gt;
Because you can define the sort function, sort allows you to create a list of keys sorting a hash by any criterion--by key, value, or (if, for instance the hash values are hashes themselves) any subvalue.&lt;br /&gt;
&lt;br /&gt;
 vec = [100,24,45];&lt;br /&gt;
 sortvec = sort (vec, func (a,b) cmp (a,b));&lt;br /&gt;
 debug.dump (sortvec); #output is [24,45,100]&lt;br /&gt;
&lt;br /&gt;
Here is an example of how to output the contents of a hash in sorted order.  Note that the function does not actually sort the hash but returns a list of the hash keys in sorted order.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
   &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
   &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
   &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) cmp (airport[a], airport[b]));&lt;br /&gt;
 &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i]);&lt;br /&gt;
&lt;br /&gt;
The output is:&lt;br /&gt;
&lt;br /&gt;
   LOWI: Innsbruck&lt;br /&gt;
   LOXL: Linz Hoersching&lt;br /&gt;
   LOXZ: Zeltweg  &lt;br /&gt;
&lt;br /&gt;
If the hash values are themselves hashes, sorting by any of the subvalues is possible.  For example:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
    &amp;quot;LOXZ&amp;quot;: {city: &amp;quot;Zeltweg&amp;quot;, altitude_m: 1300 },&lt;br /&gt;
    &amp;quot;LOWI&amp;quot;: {city: &amp;quot;Innsbruck&amp;quot;, altitude_m: 2312 }, &lt;br /&gt;
    &amp;quot;LOXL&amp;quot;: {city: &amp;quot;Linz Hoersching&amp;quot;, altitude_m: 1932 },&lt;br /&gt;
 };&lt;br /&gt;
  &lt;br /&gt;
 #return a list of the hash keys sorted by altitude_m&lt;br /&gt;
 var sortedkeys= sort (keys(airport), func (a,b) airport[a].altitude_m - airport[b].altitude_m);&lt;br /&gt;
  &lt;br /&gt;
 foreach (var i; sortedkeys) &lt;br /&gt;
  print (i, &amp;quot;: &amp;quot;, airport[i].city, &amp;quot;, &amp;quot;, airport[i].altitude_m);&lt;br /&gt;
&lt;br /&gt;
Note that ''sort'' will return errors, and in FG 2.4.0 may even stop working, if the sort function you provide returns errors.  A common cause of this is if your sort vector contains both string and numeric values.  The cmp function will return an error for numeric values, and arithmetic operations you may use to sort numeric values will return errors if performed on a string.  The error in these cases is typically &amp;quot;function/method call on uncallable object&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Other useful built-in functions ===&lt;br /&gt;
&lt;br /&gt;
Other basic built-in Nasal functions such as append, setsize, subvec, typeof, contains, delete, int, num, keys, pop, size, streq, cmp, substr, sprintf, find, split, rand, call, die, bind, math.sin, math.pi, math.exp, math.ln math.e, io.read, io.write, regex.exec, and others of that sort, [http://www.plausible.org/nasal/lib.html are detailed in this external document].&lt;br /&gt;
&lt;br /&gt;
=== Useful functions in the Nasal directory ===&lt;br /&gt;
Other functions are available in the Nasal files found in the Nasal directory of a FlightGear install.  Simply open those Nasal files in text editor to see what is inside.  Reference those functions by putting the filename in front of the function, method, variable, or object you wish to use.  For instance, to use the method Coord.new() in the file geo.nas, you simply write:&lt;br /&gt;
&lt;br /&gt;
 geo.Coord.new()&lt;br /&gt;
&lt;br /&gt;
=== Distance calculations ===&lt;br /&gt;
&lt;br /&gt;
To calculate the distance between two points (in two different ways):&lt;br /&gt;
 # mylat1, mylong1, mylat2, mylong2 are lat &amp;amp; long in degrees &lt;br /&gt;
 # myalt1 &amp;amp; myalt2 are altitude in meters&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord1 = geo.Coord.new();&lt;br /&gt;
 GeoCoord1.set_latlon(mylat1, mylong1,myalt1);&lt;br /&gt;
 &lt;br /&gt;
 var GeoCoord2 = geo.Coord.new();&lt;br /&gt;
 GeoCoord2.set_latlon(mylat2, mylong2, myalt2);&lt;br /&gt;
 &lt;br /&gt;
 var directDistance = GeoCoord1.direct_distance_to(GeoCoord2);&lt;br /&gt;
 var surfaceDistance = GeoCoord1.distance_to(GeoCoord2);&lt;br /&gt;
&lt;br /&gt;
The results are distances in meters.&lt;br /&gt;
&lt;br /&gt;
* distance_to - returns distance in meters along Earth curvature, ignoring altitudes; useful for map distance&lt;br /&gt;
* direct_distance_to - returns distance in meters direct; considers altitude, but cuts through Earth surface&lt;br /&gt;
&lt;br /&gt;
=== Other useful geographical functions ===&lt;br /&gt;
Other useful geographical functions are found in geo.nas (in the FlightGear/data/Nasal directory of a FlightGear installation). geo.nas also includes documentation/explanation of the functions available.&lt;br /&gt;
&lt;br /&gt;
==Developing and debugging in Nasal==&lt;br /&gt;
===Developing Nasal code===&lt;br /&gt;
Because code in the Nasal directory is parsed only at Flightgear startup, testing and debugging Nasal code can by slow and difficult.&lt;br /&gt;
&lt;br /&gt;
Flightgear provides a couple of ways to work around this issue:&lt;br /&gt;
&lt;br /&gt;
====Nasal Console====&lt;br /&gt;
&lt;br /&gt;
The Nasal Console is available in Flightgear's menu (Debug/Nasal Console).  Selecting this menu opens a Nasal Console dialog.&lt;br /&gt;
&lt;br /&gt;
This dialog has several tabs, of which each can hold separate Nasal code snippets, all of which are saved on exit&lt;br /&gt;
and reloaded next time. This is useful for little tests, or for executing code for which writing a key binding is just too much&lt;br /&gt;
work, such as &amp;quot;props.dump(props.globals)&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
If you want to add more tabs (radio buttons in the Nasal Console dialog) to hold more code samples, just add more &amp;amp;lt;code&amp;amp;gt; nodes to autosave.xml.&lt;br /&gt;
&lt;br /&gt;
====Loading/reloading Nasal code without re-starting Flightgear====&lt;br /&gt;
A common problem in testing and debugging Nasal programs is that each testing step requires stopping and re-starting Flightgear, a slow process.&lt;br /&gt;
&lt;br /&gt;
Below is described a technique for loading and executing a Nasal file while Flightgear is running.  Flightgear will parse the file, display any errors in the Flightgear console window, and then execute the code as usual.&lt;br /&gt;
&lt;br /&gt;
Using this technique, you can start Flightgear, load the Nasal code you want to test observe any errors or test functionality as you wish, make changes to the Nasal file, reload it to observe parse errors or change in functionality, and so on to repeatedly and quickly run through the change/load/parse/test cycle without needing to re-start Flightgear each time.&lt;br /&gt;
&lt;br /&gt;
The key to this technique is the function io.load_nasal(), which loads a nasal file into a nasal namespace. &lt;br /&gt;
&lt;br /&gt;
Step-by-step instructions showing how to use this technique to load, parse, and test a Nasal file while Flightgear is running:&lt;br /&gt;
&lt;br /&gt;
=====Create the Nasal file to test=====&lt;br /&gt;
Create a text file named $FG_ROOT/foo/test.nas with this text:&lt;br /&gt;
  &lt;br /&gt;
  print(&amp;quot;hi!&amp;quot;);&lt;br /&gt;
  var msg=&amp;quot;My message.&amp;quot;;&lt;br /&gt;
  var hello = func { print(&amp;quot;I'm the test.hello() function&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Notes: You can create the file in any directory you wish, as long as Nasal can read the directory--but the file IOrules in the Nasal directory restricts which directories Nasal may read and write from.  &lt;br /&gt;
&lt;br /&gt;
You can give the file any name and extension you wish, though it is generally most convenient to use the .nas extension with Nasal files.&lt;br /&gt;
&lt;br /&gt;
=====Load the file and test=====&lt;br /&gt;
Start Flightgear.  You can import the file above into Flightgear by typing the following into the Nasal Console dialog and executing the code:&lt;br /&gt;
&lt;br /&gt;
  io.load_nasal(getprop(&amp;quot;/sim/fg-root&amp;quot;) ~ &amp;quot;/foo/test.nas&amp;quot;, &amp;quot;example&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
getprop(&amp;quot;/sim/fg-root&amp;quot;) gets the root directory of the FlightGear installation, ~ &amp;quot;/foo/test.nas&amp;quot; appends the directory and filename you created.  The final variable &amp;quot;example&amp;quot; tells the namespace to load for the Nasal file.&lt;br /&gt;
&lt;br /&gt;
You'll see the message &amp;quot;hi!&amp;quot; on the terminal, and have function &amp;quot;example.hello()&amp;quot; immediately available. You can, for instance, type &amp;quot;example.hello();&amp;quot; into one of the Nasal console windows and press &amp;quot;Execute&amp;quot; to see the results; similarly you could execute &amp;quot;print (example.msg);&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you find errors or want to make changes, simply make them in your text editor, save the file, and execute the io.load_nasal() command again in the Nasal Console to re-load the file with changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It's worth noting that Nasal code embedded in XML GUI dialog files can be reloaded by using the &amp;quot;debug&amp;quot; menu (&amp;quot;reload GUI&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
You may also want to check out the remarks on [[Nasal_scripting_language#Memory_management|Memory management]].&lt;br /&gt;
&lt;br /&gt;
==== Managing timers and listeners ====&lt;br /&gt;
&lt;br /&gt;
Note: If your Nasal program sets listeners, timer loops, and so on, they will remain set even when the code is reloaded, and reloading the code will set additional listeners and timer loops.  &lt;br /&gt;
&lt;br /&gt;
This can lead to extremely slow framerates and unexpected behavior.  For timers you can avoid this problem by using the loopid method (described above); for listeners you can create a function to destroy all timers your Nasal program creates, and call that function before reloading the program.  (And cleaning up timer loops and listeners is a best practice for creating Nasal programs in Flightgear regardless.)&lt;br /&gt;
&lt;br /&gt;
The same problem may occur while resetting or re-initializing parts of FlightGear if your code isn't prepared for this. And obviously this applies in particular also to any worker threads you may have started, too!&lt;br /&gt;
&lt;br /&gt;
For complex Nasal scripts with many timers and listeners, it is therefore generally a very good idea to implement special callbacks so that your scripts can respond to the most important simulator &amp;quot;signals&amp;quot;, this can be achieved by registering script-specific listeners to signals like &amp;quot;reinit&amp;quot; or &amp;quot;freeze&amp;quot; (pause): the corresponding callbacks can then suspend or re-initialize the Nasal code by suspending listeners and timers. Following this practice helps ensure that your code will behave properly even during simulator resets.&lt;br /&gt;
&lt;br /&gt;
In other words, it makes sense to provide a separate high-level controller routine to look for important simulator events and then pause or re-initialize your main Nasal code as required.&lt;br /&gt;
&lt;br /&gt;
If you are using [[Nasal_scripting_language#System-wide_Nasal_code|System-wide Nasal modules]], you should register listeners to properly re-initialize and clean up your Nasal code.&lt;br /&gt;
&lt;br /&gt;
In its simplest form, this could look like this:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {}&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/reinit&amp;quot;, cleanup);&lt;br /&gt;
&lt;br /&gt;
This will invoke your &amp;quot;cleanup&amp;quot; function, whenever the &amp;quot;reinit&amp;quot; signal is set by the FlighGear core.&lt;br /&gt;
&lt;br /&gt;
Obviously, you now need to populare your cleanup function with some code, too.&lt;br /&gt;
&lt;br /&gt;
One of the easiest ways to do this, is removing all listeners/timers manually here, i.e. by adding calls to removelistener():&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func {&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
  removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This would ensure that the corresponding listeners would be removed once the signal is triggered.&lt;br /&gt;
&lt;br /&gt;
On the other hand, you could just as well use a vector of listener IDs here, and then use a Nasal foreach loop:&lt;br /&gt;
&lt;br /&gt;
 var cleanup = func(id_list) {&lt;br /&gt;
  foreach(var id; id_list)&lt;br /&gt;
   removelistener(id);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Obviously, this would require that you maintain a list of active listeners, too - so that you can actually pass a list of IDs to the cleanup function.&lt;br /&gt;
&lt;br /&gt;
This is one of those things that can be easily done in Nasal, too - just by introducing a little helper wrapper:&lt;br /&gt;
&lt;br /&gt;
 var id_list=[];&lt;br /&gt;
 var store_listener = func(id) append(id_list,id);&lt;br /&gt;
&lt;br /&gt;
The only thing required here, would be replacing/wrapping the conventional &amp;quot;setlistener&amp;quot; call with calls to your helper:&lt;br /&gt;
&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/sim/foo&amp;quot;) );&lt;br /&gt;
 store_listener( setlistener(&amp;quot;/foo/bar&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
If you were to do this consistently across all your Nasal code, you'd end up with a high level way to manage all your registered listeners centrally.&lt;br /&gt;
&lt;br /&gt;
Now, you'll probably have noticed that it would make sense to consider wrapping all these helpers and variables inside an enclosing helper class, this can be accomplished in Nasal using a hash. This would enable you to to implement everything neatly organized in an object and use RAII-like patterns to manage Nasal resources like timers, listeners and even threads.&lt;br /&gt;
&lt;br /&gt;
===Debugging===&lt;br /&gt;
The file debug.nas, included in the Nasal directory of the Flightgear distribution, has several functions useful for debugging Nasal code.  These functions are available to any Nasal program or code executed by Flightgear.&lt;br /&gt;
&lt;br /&gt;
Aside from those listed below, several other useful debugging functions are found in debug.nas; see the debug.nas file for the list of functions and explanation.&lt;br /&gt;
&lt;br /&gt;
Note that the debug module makes extensive use of ANSI terminal color codes.  These create colored output on Linux/Unix systems but on other systems they may add numerous visible control codes.  To turn off the color codes, go to the internal property tree and set&lt;br /&gt;
&lt;br /&gt;
 /sim/startup/terminal-ansi-colors=0&lt;br /&gt;
&lt;br /&gt;
Or within a Nasal program:&lt;br /&gt;
&lt;br /&gt;
 setprop (&amp;quot;/sim/startup/terminal-ansi-colors&amp;quot;,0);&lt;br /&gt;
&lt;br /&gt;
====debug.dump====&lt;br /&gt;
 debug.dump([&amp;lt;variable&amp;gt;])             ... dumps full contents of variable or of local variables if none given&lt;br /&gt;
 &lt;br /&gt;
The function debug.dump() dumps the contents of the given variable to the console. On Unix/Linux this is done with some syntax coloring. For example, these lines&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  debug.dump(as);&lt;br /&gt;
&lt;br /&gt;
would output&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;T&amp;quot; means that it's a &amp;quot;tied&amp;quot; property. The same letters are used here as in the property-browser. The angle brackets seem superfluous, but are useful because debug.dump() also outputs compound data types, such as vectors and hashes. For example:&lt;br /&gt;
&lt;br /&gt;
  var as = props.globals.getNode(&amp;quot;/velocities/airspeed-kt&amp;quot;, 1);&lt;br /&gt;
  var ac = props.globals.getNode(&amp;quot;/sim/aircraft&amp;quot;, 1);&lt;br /&gt;
  var nodes = [as, ac];&lt;br /&gt;
  var hash = { airspeed_node: as, aircraft_name: ac, all_nodes: nodes };&lt;br /&gt;
  debug.dump(hash);&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
  { all_nodes : [ &amp;lt;/velocities/airspeed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;,&lt;br /&gt;
  &amp;lt;/sim/aircraft=&amp;quot;bo105&amp;quot; (STRING)&amp;gt; ], airspeed_node : &amp;lt;/velocities/airspe&lt;br /&gt;
  ed-kt=1.021376474393101 (DOUBLE; T)&amp;gt;, aircraft_name : &amp;lt;/sim/aircraft=&amp;quot;bo&lt;br /&gt;
  105&amp;quot; (STRING)&amp;gt; }&lt;br /&gt;
&lt;br /&gt;
====debug.backtrace====&lt;br /&gt;
  debug.backtrace([&amp;lt;comment:string&amp;gt;]}  ... writes backtrace with local variables&lt;br /&gt;
  debug.bt                             ... abbreviation for debug.backtrace&lt;br /&gt;
&lt;br /&gt;
The function debug.backtrace() outputs all local variables of the current function and all parent functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====debug.benchmark====&lt;br /&gt;
debug.benchmark(&amp;lt;label:string&amp;gt;, &amp;lt;func&amp;gt; [, &amp;lt;repeat:int&amp;gt;])&lt;br /&gt;
 ... runs function &amp;lt;repeat&amp;gt; times (default: 1) and prints execution time in seconds,prefixed with &amp;lt;label&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is extremely useful for benchmarking pieces of code to determin &lt;br /&gt;
====debug.exit====&lt;br /&gt;
  debug.exit()                         ... exits fgfs&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
{{Forum|30|Nasal}}&lt;br /&gt;
* [[:Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38290</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38290"/>
		<updated>2011-12-23T02:02:54Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38289</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38289"/>
		<updated>2011-12-23T02:02:34Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
   house2.bath&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38288</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38288"/>
		<updated>2011-12-23T02:02:12Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Namespaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   house1.bath&lt;br /&gt;
&lt;br /&gt;
   house2.bath&lt;br /&gt;
&lt;br /&gt;
   house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38287</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38287"/>
		<updated>2011-12-23T02:01:38Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
&lt;br /&gt;
house2.bath&lt;br /&gt;
&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38286</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38286"/>
		<updated>2011-12-23T02:00:34Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
&lt;br /&gt;
house2.bath&lt;br /&gt;
&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38285</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38285"/>
		<updated>2011-12-23T02:00:13Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
&lt;br /&gt;
house2.bath&lt;br /&gt;
&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38284</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38284"/>
		<updated>2011-12-23T01:58:40Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Namespaces ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== More Information ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Name_spaces&amp;diff=38283</id>
		<title>Name spaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Name_spaces&amp;diff=38283"/>
		<updated>2011-12-23T01:56:33Z</updated>

		<summary type="html">&lt;p&gt;Vin: Created page with &amp;quot;Goto: http://wiki.flightgear.org/Namespaces_and_Methods&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Goto: http://wiki.flightgear.org/Namespaces_and_Methods&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Methods&amp;diff=38282</id>
		<title>Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Methods&amp;diff=38282"/>
		<updated>2011-12-23T01:55:37Z</updated>

		<summary type="html">&lt;p&gt;Vin: Created page with &amp;quot;Goto: http://wiki.flightgear.org/Namespaces_and_Methods&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Goto: http://wiki.flightgear.org/Namespaces_and_Methods&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Namespaces&amp;diff=38281</id>
		<title>Namespaces</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Namespaces&amp;diff=38281"/>
		<updated>2011-12-23T01:54:29Z</updated>

		<summary type="html">&lt;p&gt;Vin: moved Namespaces to Namespaces and Methods&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Namespaces and Methods]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38280</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38280"/>
		<updated>2011-12-23T01:54:29Z</updated>

		<summary type="html">&lt;p&gt;Vin: moved Namespaces to Namespaces and Methods&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38279</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38279"/>
		<updated>2011-12-23T01:53:29Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38278</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38278"/>
		<updated>2011-12-23T01:52:31Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Namespace]&lt;br /&gt;
[http://en.wikipedia.org/wiki/Method_%28computer_programming%29]&lt;br /&gt;
[http://en.wikipedia.org/wiki/Object-oriented_programming]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38277</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38277"/>
		<updated>2011-12-23T01:51:49Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Namespace]&lt;br /&gt;
[http://en.wikipedia.org/wiki/Method_%28computer_programming%29]&lt;br /&gt;
[http://en.wikipedia.org/wiki/Object-oriented_programming]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38276</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38276"/>
		<updated>2011-12-23T01:50:43Z</updated>

		<summary type="html">&lt;p&gt;Vin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28computer_programming%29&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-oriented_programming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38275</id>
		<title>Howto:Understand Namespaces and Methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Understand_Namespaces_and_Methods&amp;diff=38275"/>
		<updated>2011-12-23T01:49:32Z</updated>

		<summary type="html">&lt;p&gt;Vin: Created page with &amp;quot;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.  Imagine, three houses with rooms. Even otherwise identical rooms are kepts in separate &amp;quot;environ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A name space is a &amp;quot;context&amp;quot;, i.e. an environment where a certain symbol is valid.&lt;br /&gt;
&lt;br /&gt;
Imagine, three houses with rooms.&lt;br /&gt;
Even otherwise identical rooms are kepts in separate &amp;quot;environments&amp;quot;, i.e. you have to refer to a certain &amp;quot;environment&amp;quot; (namespace) to uniquely identify a certain room.&lt;br /&gt;
&lt;br /&gt;
For example, imagine three bath rooms in these three houses: house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
Now, imagine the users of the houses want to refer to each bath room using just the word (symbol/variable) &amp;quot;bath&amp;quot;. To be able to resolve this properly, they will also need to qualify what house they are referring to, i.e. if it's house1, house2, house3.&lt;br /&gt;
&lt;br /&gt;
house1.bath&lt;br /&gt;
house2.bath&lt;br /&gt;
house3.bath&lt;br /&gt;
&lt;br /&gt;
Basically, namespaces make it possible to have identically named variables/symbols without them possibly &amp;quot;clashing&amp;quot; or &amp;quot;polluting&amp;quot; the global namespace.&lt;br /&gt;
&lt;br /&gt;
Before namespaces were used, there were only &amp;quot;global variables&amp;quot;, so whenever some piece of code referred to a variable, it was possible to clash with some other similar or even unrelated uses of the variable (imagine a counter variable):&lt;br /&gt;
&lt;br /&gt;
That's when people started providing a surrounding &amp;quot;context&amp;quot; to embed variables properly.&lt;br /&gt;
In Nasal space, variables declared in functions will by default by specific to the function's scope and not be directly accessible:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    var hello = func {&lt;br /&gt;
      var x =100;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here, x is declared to be specific to the &amp;quot;hello&amp;quot; function and its namespace.&lt;br /&gt;
&lt;br /&gt;
So, basically namespaces are all about organizing and structuring your variables and the overall symbol space.&lt;br /&gt;
&lt;br /&gt;
Just imagine it like an &amp;quot;area code&amp;quot;, where people living in different countries, states, districts, counties, towns get a DIFFERENT prefix code, even though they may have the same telephone number otherwise. The international prefix number (i.e. 001 for the US) makes it obvious that the following number is a US number, same goes for local area codes (752, 642, 543).&lt;br /&gt;
&lt;br /&gt;
Methods are somewhat related to &amp;quot;namespaces&amp;quot; in that they are class-specific functions (OOP), i.e. functions that are specific to a certain instance of an already instantiated class. In Nasal space, this means that the function is embedded inside a Nasal hash and that it makes use of instance data (using &amp;quot;me&amp;quot;) or accessing the parents vector.&lt;br /&gt;
&lt;br /&gt;
For example, to switch off the lights in the bath room, there could be a method &amp;quot;switch_off_lights&amp;quot; in the &amp;quot;house&amp;quot; class:&lt;br /&gt;
&lt;br /&gt;
house.bath.switch_off_lights&lt;br /&gt;
&lt;br /&gt;
Obviously, this will only work if the switch off routine (method!) has some house to work with. The class itself really is just a &amp;quot;template&amp;quot; for functionality, before it can be used it needs to be instantiated, i.e. a new object must be created using the template, and then the member functions (methods) can be called.&lt;br /&gt;
&lt;br /&gt;
More information:&lt;br /&gt;
&lt;br /&gt;
http://en.wikipedia.org/wiki/Namespace&lt;br /&gt;
http://en.wikipedia.org/wiki/Method_%28 ... ramming%29&lt;br /&gt;
http://en.wikipedia.org/wiki/Object-ori ... rogramming&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Cessna_Citation_X&amp;diff=31470</id>
		<title>Cessna Citation X</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Cessna_Citation_X&amp;diff=31470"/>
		<updated>2011-05-02T02:53:30Z</updated>

		<summary type="html">&lt;p&gt;Vin: Added Review.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}&lt;br /&gt;
{{infobox Aircraft&lt;br /&gt;
|image = CessnaCitationX.jpg&lt;br /&gt;
|name = Cessna Citation X&lt;br /&gt;
|type = Business Jet&lt;br /&gt;
|livery =Stripes, [[Air San Francisco]]&lt;br /&gt;
|authors = Syd Adams&lt;br /&gt;
|fdm =YASim&lt;br /&gt;
|status =Development&lt;br /&gt;
|fgname =CitationX&amp;lt;/tt&amp;gt;&lt;br /&gt;
|ratingfdm =3&lt;br /&gt;
|ratingexterior =4&lt;br /&gt;
|ratingcockpit =4&lt;br /&gt;
|ratingsounds =4&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The '''Cessna Citation X''' (X as in the Roman numeral for ten, not the letter) is a long range medium business jet aircraft. The X is currently the fastest civilian jet in production with a top speed of Mach 0.92 (703 mph). This also makes it the fastest business jet in history. The Citation X is powered by two Rolls-Royce turbofan engines and is built by the Cessna Aircraft Company in Wichita, Kansas. The Citation brand of business jets encompasses six distinct &amp;quot;families&amp;quot; of aircraft. Although based on the earlier Citation III, VI and VII models the Citation X is a significantly different airplane. It utilizes a totally new wing design, engines, and features a glass cockpit.&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
&lt;br /&gt;
=== Cessna Citation X Review ===&lt;br /&gt;
&lt;br /&gt;
[http://wiki.flightgear.org/FlightGear_Newsletter_April_2011#Aircraft_reviews Click here] for a review of the Cessna Citation X.&lt;br /&gt;
&lt;br /&gt;
=== Related lists ===&lt;br /&gt;
* [[Aircraft]]&lt;br /&gt;
* [[Aircraft Todo]]&lt;br /&gt;
&lt;br /&gt;
{{Cessna}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft]]&lt;br /&gt;
[[Category:Aircraft TODO]]&lt;br /&gt;
[[Category:Cessna]]&lt;br /&gt;
[[Category:Civilian aircraft]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31379</id>
		<title>TerraSync</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31379"/>
		<updated>2011-04-29T11:46:59Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Troubleshooting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To see the terrain below your [[aircraft]], you have to install the respective [[scenery]]. This can happen by downloading certain bits of scenery before flying as described in the article [[Howto: Install scenery|installing scenery]]. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you have a steady and reasonably fast internet connection, you can use '''TerraSync'''. It is a utility that automatically downloads the newest version of the needed [[FlightGear]] [[scenery]] while the simulator is running. TerraSync runs in the background in a separate process, monitors your position, and downloads (or updates) the latest greatest scenery from the master scenery server &amp;quot;just in time&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The master repository for TerraSync, i.e. the online resource from which TerraSync downloads its files, is synchronized with the [http://scenemodels.flightgear.org/ FlightGear Scenery Database] once a day. So when using TerraSync, you will always have &lt;br /&gt;
# the latest [[File Formats#.2A.stg|.stg-files]], which tell FlightGear where to place an object &lt;br /&gt;
# the latest '''static''' models for objects. (Static models define unique objects that exist in one place only, such as famous buildings or landmarks.) &lt;br /&gt;
&lt;br /&gt;
As of March 2011, TerraSync also downloads '''shared''' models (generic models used more than once in different places, each can represent many different objects, like generic houses or ships), at least when it first runs. It does not, however, install the shared models, and until they are installed in the right place, you won't see any objects that are based on them. You will need to copy all the files from the Models directory inside your TerraSync directory to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;, replacing the files that are already there. If for some reason you suspect your models are not up-to-date, you can also manually download the newest [http://scenemodels.flightgear.org/download/SharedModels.tgz '''shared''' models archive] from the [http://scenemodels.flightgear.org/ FlightGear Scenery Database]. Unpack it to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to use a separate scenery directory for TerraSync (i.e. do not run have it store its downloaded files in your main scenery directory) because network interruptions may upset the synchronization protocol and garble what is stored there. If/when that happens the easiest solution is to delete the affected subdirectory and let terrasync download it again (see [[Howto:_Animated_jetways#Usage]].&lt;br /&gt;
&lt;br /&gt;
=== Usage example (for POSIX compliant [[command line]] shell) ===&lt;br /&gt;
&lt;br /&gt;
Start terrasync:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% nice terrasync -p 5500 -S -d &amp;quot;$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -S option tells terrasync to use the SVN protocol to fetch data. If you omit it terrasync will use the rsync program instead (which has to be installed on your system).&lt;br /&gt;
&lt;br /&gt;
Start FlightGear:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% fgfs --atlas=socket,out,1,localhost,5500,udp --fg-scenery=&amp;quot;[[$FG_ROOT]]/Scenery/:$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full documentation and source for TerraSync is located in the FlightGear source distribution (in &amp;lt;code&amp;gt;utils/TerraSync/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Start TerraSync from [[FGRun]] in FlightGear 1.9.1 ===&lt;br /&gt;
# Make sure you are in the first screen where you can set up directories. To get there, start fgrun.exe. You'll first be in the Aircraft selection screen, then hit &amp;quot;Back&amp;quot;. You are now here:&amp;lt;br/&amp;gt;[[File:TerraSync 1.png]]&lt;br /&gt;
# Select the destination folder for all files downloaded by terrasync. Usually the folder &amp;lt;code&amp;gt;[[$FG_ROOT]]\terrasync&amp;lt;/code&amp;gt; already exists and you only have to add it to the list (as in the above example). Insure that it is positioned '''above''' your standard scenery folder (here that is &amp;lt;code&amp;gt;FlightGear191\scenery&amp;lt;/code&amp;gt;) and all other directories over which the terrasync folder is supposed to have priority. When two directories contain information for the same region, FlightGear will take the information from the directory higher in the list. On Linux make sure the directory does not only to have a T, but also is the topmost folder.&lt;br /&gt;
# For TerraSync to know where to deposit the downloaded files, you have to tell the program which folder is the destination folder. In the above example, it is the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; in the list.&lt;br /&gt;
# Finally, go to the last screen. There you have to activate TerraSync as in the following screenshot. Now TerraSync should work.&amp;lt;br /&amp;gt;[[File:TerraSync 2.png]]&lt;br /&gt;
&lt;br /&gt;
''Note: Expect your firewall to block it the first time you run it; just tell the firewall to allow TerraSync to use the port.''&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
If you get an error similar to the following in the command line console (black dialog):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Airports/L ... failed:&lt;br /&gt;
 Can't move 'C:\FlightGear\terrasync\Airports\L\E\.svn\tmp\entries' to 'C:\FlightGear\terrasync\Airports\L\E\.svn\entries': The file or directory is corrupted and unreadable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and possibly the following popup appears:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Taskbar Error.png]]&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
You can probably fix the error by upgrading to Windows 7 Home Premium Service Pack 1.&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
* [[Howto: Install scenery]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31378</id>
		<title>TerraSync</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31378"/>
		<updated>2011-04-29T11:39:14Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Problem */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To see the terrain below your [[aircraft]], you have to install the respective [[scenery]]. This can happen by downloading certain bits of scenery before flying as described in the article [[Howto: Install scenery|installing scenery]]. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you have a steady and reasonably fast internet connection, you can use '''TerraSync'''. It is a utility that automatically downloads the newest version of the needed [[FlightGear]] [[scenery]] while the simulator is running. TerraSync runs in the background in a separate process, monitors your position, and downloads (or updates) the latest greatest scenery from the master scenery server &amp;quot;just in time&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The master repository for TerraSync, i.e. the online resource from which TerraSync downloads its files, is synchronized with the [http://scenemodels.flightgear.org/ FlightGear Scenery Database] once a day. So when using TerraSync, you will always have &lt;br /&gt;
# the latest [[File Formats#.2A.stg|.stg-files]], which tell FlightGear where to place an object &lt;br /&gt;
# the latest '''static''' models for objects. (Static models define unique objects that exist in one place only, such as famous buildings or landmarks.) &lt;br /&gt;
&lt;br /&gt;
As of March 2011, TerraSync also downloads '''shared''' models (generic models used more than once in different places, each can represent many different objects, like generic houses or ships), at least when it first runs. It does not, however, install the shared models, and until they are installed in the right place, you won't see any objects that are based on them. You will need to copy all the files from the Models directory inside your TerraSync directory to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;, replacing the files that are already there. If for some reason you suspect your models are not up-to-date, you can also manually download the newest [http://scenemodels.flightgear.org/download/SharedModels.tgz '''shared''' models archive] from the [http://scenemodels.flightgear.org/ FlightGear Scenery Database]. Unpack it to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to use a separate scenery directory for TerraSync (i.e. do not run have it store its downloaded files in your main scenery directory) because network interruptions may upset the synchronization protocol and garble what is stored there. If/when that happens the easiest solution is to delete the affected subdirectory and let terrasync download it again (see [[Howto:_Animated_jetways#Usage]].&lt;br /&gt;
&lt;br /&gt;
=== Usage example (for POSIX compliant [[command line]] shell) ===&lt;br /&gt;
&lt;br /&gt;
Start terrasync:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% nice terrasync -p 5500 -S -d &amp;quot;$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -S option tells terrasync to use the SVN protocol to fetch data. If you omit it terrasync will use the rsync program instead (which has to be installed on your system).&lt;br /&gt;
&lt;br /&gt;
Start FlightGear:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% fgfs --atlas=socket,out,1,localhost,5500,udp --fg-scenery=&amp;quot;[[$FG_ROOT]]/Scenery/:$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full documentation and source for TerraSync is located in the FlightGear source distribution (in &amp;lt;code&amp;gt;utils/TerraSync/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Start TerraSync from [[FGRun]] in FlightGear 1.9.1 ===&lt;br /&gt;
# Make sure you are in the first screen where you can set up directories. To get there, start fgrun.exe. You'll first be in the Aircraft selection screen, then hit &amp;quot;Back&amp;quot;. You are now here:&amp;lt;br/&amp;gt;[[File:TerraSync 1.png]]&lt;br /&gt;
# Select the destination folder for all files downloaded by terrasync. Usually the folder &amp;lt;code&amp;gt;[[$FG_ROOT]]\terrasync&amp;lt;/code&amp;gt; already exists and you only have to add it to the list (as in the above example). Insure that it is positioned '''above''' your standard scenery folder (here that is &amp;lt;code&amp;gt;FlightGear191\scenery&amp;lt;/code&amp;gt;) and all other directories over which the terrasync folder is supposed to have priority. When two directories contain information for the same region, FlightGear will take the information from the directory higher in the list. On Linux make sure the directory does not only to have a T, but also is the topmost folder.&lt;br /&gt;
# For TerraSync to know where to deposit the downloaded files, you have to tell the program which folder is the destination folder. In the above example, it is the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; in the list.&lt;br /&gt;
# Finally, go to the last screen. There you have to activate TerraSync as in the following screenshot. Now TerraSync should work.&amp;lt;br /&amp;gt;[[File:TerraSync 2.png]]&lt;br /&gt;
&lt;br /&gt;
''Note: Expect your firewall to block it the first time you run it; just tell the firewall to allow TerraSync to use the port.''&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
If you get an error similar to the following in the command line console (black dialog):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Airports/L ... failed:&lt;br /&gt;
 Can't move 'C:\FlightGear\terrasync\Airports\L\E\.svn\tmp\entries' to 'C:\FlightGear\terrasync\Airports\L\E\.svn\entries': The file or directory is corrupted and unreadable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and possibly the following popup appears:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Taskbar Error.png]]&lt;br /&gt;
&lt;br /&gt;
you can probably fix the error by upgrading to Windows 7 Home Premium Service Pack 1.&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
* [[Howto: Install scenery]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31377</id>
		<title>TerraSync</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31377"/>
		<updated>2011-04-29T11:38:04Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Problem */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To see the terrain below your [[aircraft]], you have to install the respective [[scenery]]. This can happen by downloading certain bits of scenery before flying as described in the article [[Howto: Install scenery|installing scenery]]. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you have a steady and reasonably fast internet connection, you can use '''TerraSync'''. It is a utility that automatically downloads the newest version of the needed [[FlightGear]] [[scenery]] while the simulator is running. TerraSync runs in the background in a separate process, monitors your position, and downloads (or updates) the latest greatest scenery from the master scenery server &amp;quot;just in time&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The master repository for TerraSync, i.e. the online resource from which TerraSync downloads its files, is synchronized with the [http://scenemodels.flightgear.org/ FlightGear Scenery Database] once a day. So when using TerraSync, you will always have &lt;br /&gt;
# the latest [[File Formats#.2A.stg|.stg-files]], which tell FlightGear where to place an object &lt;br /&gt;
# the latest '''static''' models for objects. (Static models define unique objects that exist in one place only, such as famous buildings or landmarks.) &lt;br /&gt;
&lt;br /&gt;
As of March 2011, TerraSync also downloads '''shared''' models (generic models used more than once in different places, each can represent many different objects, like generic houses or ships), at least when it first runs. It does not, however, install the shared models, and until they are installed in the right place, you won't see any objects that are based on them. You will need to copy all the files from the Models directory inside your TerraSync directory to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;, replacing the files that are already there. If for some reason you suspect your models are not up-to-date, you can also manually download the newest [http://scenemodels.flightgear.org/download/SharedModels.tgz '''shared''' models archive] from the [http://scenemodels.flightgear.org/ FlightGear Scenery Database]. Unpack it to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is recommended to use a separate scenery directory for TerraSync (i.e. do not run have it store its downloaded files in your main scenery directory) because network interruptions may upset the synchronization protocol and garble what is stored there. If/when that happens the easiest solution is to delete the affected subdirectory and let terrasync download it again (see [[Howto:_Animated_jetways#Usage]].&lt;br /&gt;
&lt;br /&gt;
=== Usage example (for POSIX compliant [[command line]] shell) ===&lt;br /&gt;
&lt;br /&gt;
Start terrasync:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% nice terrasync -p 5500 -S -d &amp;quot;$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -S option tells terrasync to use the SVN protocol to fetch data. If you omit it terrasync will use the rsync program instead (which has to be installed on your system).&lt;br /&gt;
&lt;br /&gt;
Start FlightGear:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% fgfs --atlas=socket,out,1,localhost,5500,udp --fg-scenery=&amp;quot;[[$FG_ROOT]]/Scenery/:$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full documentation and source for TerraSync is located in the FlightGear source distribution (in &amp;lt;code&amp;gt;utils/TerraSync/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Start TerraSync from [[FGRun]] in FlightGear 1.9.1 ===&lt;br /&gt;
# Make sure you are in the first screen where you can set up directories. To get there, start fgrun.exe. You'll first be in the Aircraft selection screen, then hit &amp;quot;Back&amp;quot;. You are now here:&amp;lt;br/&amp;gt;[[File:TerraSync 1.png]]&lt;br /&gt;
# Select the destination folder for all files downloaded by terrasync. Usually the folder &amp;lt;code&amp;gt;[[$FG_ROOT]]\terrasync&amp;lt;/code&amp;gt; already exists and you only have to add it to the list (as in the above example). Insure that it is positioned '''above''' your standard scenery folder (here that is &amp;lt;code&amp;gt;FlightGear191\scenery&amp;lt;/code&amp;gt;) and all other directories over which the terrasync folder is supposed to have priority. When two directories contain information for the same region, FlightGear will take the information from the directory higher in the list. On Linux make sure the directory does not only to have a T, but also is the topmost folder.&lt;br /&gt;
# For TerraSync to know where to deposit the downloaded files, you have to tell the program which folder is the destination folder. In the above example, it is the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; in the list.&lt;br /&gt;
# Finally, go to the last screen. There you have to activate TerraSync as in the following screenshot. Now TerraSync should work.&amp;lt;br /&amp;gt;[[File:TerraSync 2.png]]&lt;br /&gt;
&lt;br /&gt;
''Note: Expect your firewall to block it the first time you run it; just tell the firewall to allow TerraSync to use the port.''&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
If you get an error similar to the following in the console (black dialog):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Airports/L ... failed:&lt;br /&gt;
 Can't move 'C:\FlightGear\terrasync\Airports\L\E\.svn\tmp\entries' to 'C:\FlightGear\terrasync\Airports\L\E\.svn\entries': The file or directory is corrupted and unreadable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and possibly the following popup appears:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Taskbar Error.png]]&lt;br /&gt;
&lt;br /&gt;
you can probably fix the error by upgrading to Windows 7 Home Premium Service Pack 1.&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
* [[Howto: Install scenery]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31149</id>
		<title>TerraSync</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31149"/>
		<updated>2011-04-21T09:31:46Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Problem */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To see the terrain below your aircraft, you have to install the respective [[scenery]]. This can happen by downloading certain bits of scenery before flying as described in the article [[Installing Scenery]]. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you have a steady and reasonably fast internet connection, you can use '''TerraSync'''. It is a utility that automatically downloads the newest version of the needed [[FlightGear]] [[scenery]] while the simulator is running. TerraSync runs in the background in a separate process, monitors your position, and downloads (or updates) the latest greatest scenery from the master scenery server &amp;quot;just in time&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The master repository for terrasync, i.e. the online resource from which TerraSync downloads its files, is synchronized with the [http://scenemodels.flightgear.org/ FlightGear Scenery Database] once a day. So when using TerraSync, you will always have 1) the latest [[File Formats#.2A.stg|.stg-files]], which tell FlightGear where to place an object and 2) the latest '''static''' models for objects. (Static models define unique objects that exist in one place only, such as famous buildings or landmarks.) &lt;br /&gt;
&lt;br /&gt;
As of March 2011, TerraSync also downloads '''shared''' models, at least when it first runs.  (Shared models are generic models used more than once in different places, each can represent many different objects, like generic houses or ships.)  It does not, however, install the shared models, and until they are installed in the right place, you won't see any objects that are based on them.  You will need to copy all the files from the Models directory inside your TerraSync directory to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;, replacing the files that are already there.  (If for some reason you suspect your models are not up-to-date, you can also manually download the newest [http://scenemodels.flightgear.org/download/SharedModels.tgz '''shared''' models archive] from the [http://scenemodels.flightgear.org/ FlightGear Scenery Database].  Unpack it to &amp;lt;code&amp;gt;$FG_ROOT/Models&amp;lt;/code&amp;gt;.  See also: [[Howto: Animated jetways#Usage]].)&lt;br /&gt;
&lt;br /&gt;
It is recommended to use a separate scenery directory for TerraSync (i.e. do not run have it store its downloaded files in your main scenery directory) because network interruptions may upset the synchronization protocol and garble what is stored there.  If/when that happens the easiest solution is to delete the affected subdirectory and let terrasync download it again.&lt;br /&gt;
&lt;br /&gt;
=== Usage example (for POSIX compliant [[command line]] shell) ===&lt;br /&gt;
&lt;br /&gt;
Start terrasync:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% nice terrasync -p 5500 -S -d &amp;quot;$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -S option tells terrasync to use the SVN protocol to fetch data. If you omit it terrasync will use the rsync program instead (which has to be installed on your system).&lt;br /&gt;
&lt;br /&gt;
Start FlightGear:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% fgfs --atlas=socket,out,1,localhost,5500,udp --fg-scenery=&amp;quot;$FG_ROOT/Scenery/:$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full documentation and source for TerraSync is located in the FlightGear source distribution (in &amp;lt;code&amp;gt;utils/TerraSync/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Start TerraSync from fgrun.exe (Wizard in Windows) in FlightGear 1.9.1 ===&lt;br /&gt;
&lt;br /&gt;
1. Make sure you are in the first screen where you can set up directories. To get there, start fgrun.exe. You'll first be in the Aircraft selection screen, then hit &amp;quot;Back&amp;quot;. You are now here:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync 1.png]]&lt;br /&gt;
&lt;br /&gt;
2. Select the destination folder for all files downloaded by terrasync. Usually the folder &amp;lt;code&amp;gt;[FG_ROOT]\terrasync&amp;lt;/code&amp;gt; already exists and you only have to add it to the list (as in the above example). Insure that it is positioned '''above''' your standard scenery folder (here that is &amp;lt;code&amp;gt;FlightGear191\scenery&amp;lt;/code&amp;gt;) and all other directories over which the terrasync folder is supposed to have priority. When two directories contain information for the same region, FlightGear will take the information from the directory higher in the list. On Linux make sure the directory does not only to have a T, but also is the topmost folder.&lt;br /&gt;
&lt;br /&gt;
3. For TerraSync to know where to deposit the downloaded files, you have to tell the program which folder is the destination folder. In the above example, it is the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; in the list.&lt;br /&gt;
&lt;br /&gt;
4. Finally, go to the last screen. There you have to activate TerraSync as in the following screenshot. Now TerraSync should work.&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync 2.png]]&lt;br /&gt;
&lt;br /&gt;
''Note: Expect your firewall to block it the first time you run it; just tell the firewall to allow TerraSync to use the port.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
If you get an error similar to the following in the command line window;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Airports/L ... failed:&lt;br /&gt;
Can't move 'C:\FlightGear\terrasync\Airports\L\E\.svn\tmp\entries' to 'C:\FlightGear\terrasync\Airports\L\E\.svn\entries': The file or directory is corrupted and unreadable.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This thing pops up in my taskbar:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Taskbar Error.png]]&lt;br /&gt;
&lt;br /&gt;
These errors pop up in the command line window:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Download Error Screen Version 6 Good Version.png]]&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Upgrade to Windows 7 Home Premium Service Pack 1.&lt;br /&gt;
&lt;br /&gt;
PLEASE READ THIS FORUM VERY CAREFULLY:&lt;br /&gt;
&lt;br /&gt;
http://www.flightgear.org/forums/viewtopic.php?f=17&amp;amp;t=11353&amp;amp;p=118393#p118393&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See [[Installing Scenery]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31148</id>
		<title>TerraSync</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31148"/>
		<updated>2011-04-21T09:31:17Z</updated>

		<summary type="html">&lt;p&gt;Vin: Undo revision 31147 by Vin (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To see the terrain below your aircraft, you have to install the respective [[scenery]]. This can happen by downloading certain bits of scenery before flying as described in the article [[Installing Scenery]]. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you have a steady and reasonably fast internet connection, you can use '''TerraSync'''. It is a utility that automatically downloads the newest version of the needed [[FlightGear]] [[scenery]] while the simulator is running. TerraSync runs in the background in a separate process, monitors your position, and downloads (or updates) the latest greatest scenery from the master scenery server &amp;quot;just in time&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The master repository for terrasync, i.e. the online resource from which TerraSync downloads its files, is synchronized with the [http://scenemodels.flightgear.org/ FlightGear Scenery Database] once a day. So when using TerraSync, you will always have 1) the latest [[File Formats#.2A.stg|.stg-files]], which tell FlightGear where to place an object and 2) the latest '''static''' models for objects. (Static models define unique objects that exist in one place only, such as famous buildings or landmarks.) &lt;br /&gt;
&lt;br /&gt;
As of March 2011, TerraSync also downloads '''shared''' models, at least when it first runs.  (Shared models are generic models used more than once in different places, each can represent many different objects, like generic houses or ships.)  It does not, however, install the shared models, and until they are installed in the right place, you won't see any objects that are based on them.  You will need to copy all the files from the Models directory inside your TerraSync directory to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;, replacing the files that are already there.  (If for some reason you suspect your models are not up-to-date, you can also manually download the newest [http://scenemodels.flightgear.org/download/SharedModels.tgz '''shared''' models archive] from the [http://scenemodels.flightgear.org/ FlightGear Scenery Database].  Unpack it to &amp;lt;code&amp;gt;$FG_ROOT/Models&amp;lt;/code&amp;gt;.  See also: [[Howto: Animated jetways#Usage]].)&lt;br /&gt;
&lt;br /&gt;
It is recommended to use a separate scenery directory for TerraSync (i.e. do not run have it store its downloaded files in your main scenery directory) because network interruptions may upset the synchronization protocol and garble what is stored there.  If/when that happens the easiest solution is to delete the affected subdirectory and let terrasync download it again.&lt;br /&gt;
&lt;br /&gt;
=== Usage example (for POSIX compliant [[command line]] shell) ===&lt;br /&gt;
&lt;br /&gt;
Start terrasync:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% nice terrasync -p 5500 -S -d &amp;quot;$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -S option tells terrasync to use the SVN protocol to fetch data. If you omit it terrasync will use the rsync program instead (which has to be installed on your system).&lt;br /&gt;
&lt;br /&gt;
Start FlightGear:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% fgfs --atlas=socket,out,1,localhost,5500,udp --fg-scenery=&amp;quot;$FG_ROOT/Scenery/:$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full documentation and source for TerraSync is located in the FlightGear source distribution (in &amp;lt;code&amp;gt;utils/TerraSync/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Start TerraSync from fgrun.exe (Wizard in Windows) in FlightGear 1.9.1 ===&lt;br /&gt;
&lt;br /&gt;
1. Make sure you are in the first screen where you can set up directories. To get there, start fgrun.exe. You'll first be in the Aircraft selection screen, then hit &amp;quot;Back&amp;quot;. You are now here:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync 1.png]]&lt;br /&gt;
&lt;br /&gt;
2. Select the destination folder for all files downloaded by terrasync. Usually the folder &amp;lt;code&amp;gt;[FG_ROOT]\terrasync&amp;lt;/code&amp;gt; already exists and you only have to add it to the list (as in the above example). Insure that it is positioned '''above''' your standard scenery folder (here that is &amp;lt;code&amp;gt;FlightGear191\scenery&amp;lt;/code&amp;gt;) and all other directories over which the terrasync folder is supposed to have priority. When two directories contain information for the same region, FlightGear will take the information from the directory higher in the list. On Linux make sure the directory does not only to have a T, but also is the topmost folder.&lt;br /&gt;
&lt;br /&gt;
3. For TerraSync to know where to deposit the downloaded files, you have to tell the program which folder is the destination folder. In the above example, it is the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; in the list.&lt;br /&gt;
&lt;br /&gt;
4. Finally, go to the last screen. There you have to activate TerraSync as in the following screenshot. Now TerraSync should work.&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync 2.png]]&lt;br /&gt;
&lt;br /&gt;
''Note: Expect your firewall to block it the first time you run it; just tell the firewall to allow TerraSync to use the port.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
If you get an error similar to the following in the command line window;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Airports/L ... failed:&lt;br /&gt;
Can't move 'C:\FlightGear\terrasync\Airports\L\E\.svn\tmp\entries' to 'C:\FlightGear\terrasync\Airports\L\E\.svn\entries': The file or directory is corrupted and unreadable.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This thing pops up in my taskbar:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Taskbar Error.png]]&lt;br /&gt;
&lt;br /&gt;
These errors pop up in the command line window:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Download Error Screen.png]]&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Upgrade to Windows 7 Home Premium Service Pack 1.&lt;br /&gt;
&lt;br /&gt;
PLEASE READ THIS FORUM VERY CAREFULLY:&lt;br /&gt;
&lt;br /&gt;
http://www.flightgear.org/forums/viewtopic.php?f=17&amp;amp;t=11353&amp;amp;p=118393#p118393&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See [[Installing Scenery]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31147</id>
		<title>TerraSync</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=TerraSync&amp;diff=31147"/>
		<updated>2011-04-21T09:29:06Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Problem */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To see the terrain below your aircraft, you have to install the respective [[scenery]]. This can happen by downloading certain bits of scenery before flying as described in the article [[Installing Scenery]]. &lt;br /&gt;
&lt;br /&gt;
Alternatively, if you have a steady and reasonably fast internet connection, you can use '''TerraSync'''. It is a utility that automatically downloads the newest version of the needed [[FlightGear]] [[scenery]] while the simulator is running. TerraSync runs in the background in a separate process, monitors your position, and downloads (or updates) the latest greatest scenery from the master scenery server &amp;quot;just in time&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The master repository for terrasync, i.e. the online resource from which TerraSync downloads its files, is synchronized with the [http://scenemodels.flightgear.org/ FlightGear Scenery Database] once a day. So when using TerraSync, you will always have 1) the latest [[File Formats#.2A.stg|.stg-files]], which tell FlightGear where to place an object and 2) the latest '''static''' models for objects. (Static models define unique objects that exist in one place only, such as famous buildings or landmarks.) &lt;br /&gt;
&lt;br /&gt;
As of March 2011, TerraSync also downloads '''shared''' models, at least when it first runs.  (Shared models are generic models used more than once in different places, each can represent many different objects, like generic houses or ships.)  It does not, however, install the shared models, and until they are installed in the right place, you won't see any objects that are based on them.  You will need to copy all the files from the Models directory inside your TerraSync directory to &amp;lt;code&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/code&amp;gt;, replacing the files that are already there.  (If for some reason you suspect your models are not up-to-date, you can also manually download the newest [http://scenemodels.flightgear.org/download/SharedModels.tgz '''shared''' models archive] from the [http://scenemodels.flightgear.org/ FlightGear Scenery Database].  Unpack it to &amp;lt;code&amp;gt;$FG_ROOT/Models&amp;lt;/code&amp;gt;.  See also: [[Howto: Animated jetways#Usage]].)&lt;br /&gt;
&lt;br /&gt;
It is recommended to use a separate scenery directory for TerraSync (i.e. do not run have it store its downloaded files in your main scenery directory) because network interruptions may upset the synchronization protocol and garble what is stored there.  If/when that happens the easiest solution is to delete the affected subdirectory and let terrasync download it again.&lt;br /&gt;
&lt;br /&gt;
=== Usage example (for POSIX compliant [[command line]] shell) ===&lt;br /&gt;
&lt;br /&gt;
Start terrasync:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% nice terrasync -p 5500 -S -d &amp;quot;$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -S option tells terrasync to use the SVN protocol to fetch data. If you omit it terrasync will use the rsync program instead (which has to be installed on your system).&lt;br /&gt;
&lt;br /&gt;
Start FlightGear:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;% fgfs --atlas=socket,out,1,localhost,5500,udp --fg-scenery=&amp;quot;$FG_ROOT/Scenery/:$HOME/fgfsScenery&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full documentation and source for TerraSync is located in the FlightGear source distribution (in &amp;lt;code&amp;gt;utils/TerraSync/&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Start TerraSync from fgrun.exe (Wizard in Windows) in FlightGear 1.9.1 ===&lt;br /&gt;
&lt;br /&gt;
1. Make sure you are in the first screen where you can set up directories. To get there, start fgrun.exe. You'll first be in the Aircraft selection screen, then hit &amp;quot;Back&amp;quot;. You are now here:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync 1.png]]&lt;br /&gt;
&lt;br /&gt;
2. Select the destination folder for all files downloaded by terrasync. Usually the folder &amp;lt;code&amp;gt;[FG_ROOT]\terrasync&amp;lt;/code&amp;gt; already exists and you only have to add it to the list (as in the above example). Insure that it is positioned '''above''' your standard scenery folder (here that is &amp;lt;code&amp;gt;FlightGear191\scenery&amp;lt;/code&amp;gt;) and all other directories over which the terrasync folder is supposed to have priority. When two directories contain information for the same region, FlightGear will take the information from the directory higher in the list. On Linux make sure the directory does not only to have a T, but also is the topmost folder.&lt;br /&gt;
&lt;br /&gt;
3. For TerraSync to know where to deposit the downloaded files, you have to tell the program which folder is the destination folder. In the above example, it is the 3&amp;lt;sup&amp;gt;rd&amp;lt;/sup&amp;gt; in the list.&lt;br /&gt;
&lt;br /&gt;
4. Finally, go to the last screen. There you have to activate TerraSync as in the following screenshot. Now TerraSync should work.&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync 2.png]]&lt;br /&gt;
&lt;br /&gt;
''Note: Expect your firewall to block it the first time you run it; just tell the firewall to allow TerraSync to use the port.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
=== Problem ===&lt;br /&gt;
&lt;br /&gt;
If you get an error similar to the following in the command line window;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Airports/L ... failed:&lt;br /&gt;
Can't move 'C:\FlightGear\terrasync\Airports\L\E\.svn\tmp\entries' to 'C:\FlightGear\terrasync\Airports\L\E\.svn\entries': The file or directory is corrupted and unreadable.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This thing pops up in my taskbar:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Download Error Screen Version 6 Good Version.png]]&lt;br /&gt;
&lt;br /&gt;
These errors pop up in the command line window:&lt;br /&gt;
&lt;br /&gt;
[[File:TerraSync Download Error Screen.png]]&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
Upgrade to Windows 7 Home Premium Service Pack 1.&lt;br /&gt;
&lt;br /&gt;
PLEASE READ THIS FORUM VERY CAREFULLY:&lt;br /&gt;
&lt;br /&gt;
http://www.flightgear.org/forums/viewtopic.php?f=17&amp;amp;t=11353&amp;amp;p=118393#p118393&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See [[Installing Scenery]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:TerraSync_Download_Error_Screen_Version_6_Good_Version.png&amp;diff=31146</id>
		<title>File:TerraSync Download Error Screen Version 6 Good Version.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:TerraSync_Download_Error_Screen_Version_6_Good_Version.png&amp;diff=31146"/>
		<updated>2011-04-21T09:28:25Z</updated>

		<summary type="html">&lt;p&gt;Vin: TerraSync Download Error. The file or directory is corrupted and unreadable... Version 6&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TerraSync Download Error. The file or directory is corrupted and unreadable... Version 6&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31130</id>
		<title>FlightGear Newsletter April 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31130"/>
		<updated>2011-04-20T07:25:18Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* New instruments */ Fixed Spelling error&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
''We would like to emphasize that the monthly newsletter can not live without the contributions of FlightGear users and developers. Everyone with a wiki account (free to register) can edit the newsletter and every contribution is welcome. So if you know about any FlightGear related projects such as for example updated scenery or aircraft, please do feel invited to add such news to the newsletter.''&lt;br /&gt;
&lt;br /&gt;
== Development news ==&lt;br /&gt;
=== Atmospheric scattering shader ===&lt;br /&gt;
Zan has been working very hard on an experimental atmospheric scattering [[shader]]. The shaders makes use of [http://sponeil.net/ Sean O'Neil's algorithm]. Altough there are some issues with the shader, it looks like it will have a promising future!&lt;br /&gt;
&lt;br /&gt;
=== Doctor Who Fans ===&lt;br /&gt;
[[Image:Tardis colour.png|thumb|Doctor Who TARDIS]]&lt;br /&gt;
Vinura has started work on developing a [http://en.wikipedia.org/wiki/TARDIS#The_Doctor.27s_TARDIS Doctor Who TARDIS] for FlightGear. The exterior model is almost complete in SketchUp. Click [http://www.flightgear.org/forums/viewtopic.php?f=4&amp;amp;t=11738 here] for the development thread.&lt;br /&gt;
&lt;br /&gt;
Currently, I still need to get the TARDIS colours right as I am only allowed to use 'Named Colours' from Google SketchUp as they can't claim copyright on colours.&lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
=== New instruments ===&lt;br /&gt;
The [[Boeing 777-200ER]]'s chronometer has been moved to the generic instruments directory (&amp;lt;tt&amp;gt;Aircraft/Instruments-3d/chronometer&amp;lt;/tt&amp;gt;). This allows aircraft developers to easily implement this clock in their aircraft. All related Nasal code was included in the model xml file, so there's really just one file to be linked to! Some aircraft already make use of this clock, including the [[Boeing 747-400]] and [[Boeing 757-200|757-200]]. &lt;br /&gt;
&lt;br /&gt;
There are several advantages in moving instruments to the generic directory, some of which are:&lt;br /&gt;
* Easy to be re-used in other aircraft, all you need to do is link to (and position) the model and on some instruments link to a Nasal file.&lt;br /&gt;
* If someone extents the functionality of a generic instrument, it will be automatically extended in all the aircraft that use it.&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
=== Vostok-1 ===&lt;br /&gt;
[[Image:Vostok-1-Carrier-News.png|thumb|Vostok-1 Carrier]]&lt;br /&gt;
[[Image:Vostok-1-News.png|thumb|Vostok-1 Spacecraft]]&lt;br /&gt;
[[Image:Vostok-1-Interior-News.png|thumb|Vostok-1 Interior]]&lt;br /&gt;
To celebrate Yury Gagarin's historical flight, [[Vostok-1]] carrier and spacecraft were added to FlightGear. In heavy development still, it already allows full orbital flight from lift-off to landing, making it perform the first spaceflight in FlightGear. &lt;br /&gt;
&lt;br /&gt;
Things that make it possible:&lt;br /&gt;
*[[JSBSim]] centrifugal force addition made the whole flight available.&lt;br /&gt;
*JSBSim property driven point masses, tanks and engines, and aerodynamic coefficients implementation allow stages changing. Each single stage of the flight has an independent mass scheme, propulsion system, and aerodynamics reactions, so simulation is more or less realistic.&lt;br /&gt;
*Datcom+ with &amp;quot;little wing&amp;quot; approach resolves carrier and spacecraft aerodynamics accurately enough to make flights on real fuel and oxidizer capacities with real g forces, orbit and deorbit paths. &lt;br /&gt;
*[[FlightGear Newsletter April 2011#Atmospheric scattering shader|Zan's shader]] makes the earth look pretty enough from high altitudes.&lt;br /&gt;
*FG improvement shifted practical flight ceiling from 80 to 160 kilometers.&lt;br /&gt;
&lt;br /&gt;
In real life, the first human spaceflight was fully automated. In FlightGear, instead controls are completely manual to make it interesting, and to make you understand how it really works.&lt;br /&gt;
&lt;br /&gt;
Authors and developers, since orbital flight is possible in FlightGear from now on, you are invited to make a FlightGear driven Mercury-Atlas project. Low earth orbit flights can be more exact and eyecandy in FlightGear than in any current simulator. And you can be sure it will be free for you and users in any case.&lt;br /&gt;
&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
[[Image:Fgfs-screen-072.png|thumb|Airbus A320]]&lt;br /&gt;
[[Image:Fgfs-screen-089.png|thumb|Boeing 767]]&lt;br /&gt;
Some [http://liveries.flightgear.org/airlines.php?id=231 SriLankan Airlines] liveries have been made by Vinura for the Boeing 767 and Airbus A320.&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
&lt;br /&gt;
=== New scenery ===&lt;br /&gt;
New third-party scenery for the USA's Pacific Northwest (Seattle and Portland, OR) and Rio de Janeiro is now available for download at http://www.stattosoftware.com/flightgear&lt;br /&gt;
&lt;br /&gt;
=== New Buildings ===&lt;br /&gt;
Once again, there are new Eastern Asian buildings !&lt;br /&gt;
&lt;br /&gt;
* Saigon Center - Ho Chi Minh City - Vietnam&lt;br /&gt;
* Mode Gakuen Coccoon Tower - Tokyo - Japan&lt;br /&gt;
* Trade Tower - Seoul - South Korea&lt;br /&gt;
* Koryo Hotel - Pyongyang - North Korea&lt;br /&gt;
* The Center - Hong Kong - China&lt;br /&gt;
* Central Plaza - Hong Kong - China&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
The generic Concourse C at KDEN was recently replaced with a much better, realistic working model featuring animated jetways. Please enjoy.&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
SriLankan Airlines livery on an Airbus A320 taken at dusk.&lt;br /&gt;
&lt;br /&gt;
[[File:Fgfs-screen-085.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
Departing from Brisbane International Airport and heading towards Sydney International Airport at a heading of about 203, you will come across some beautiful scenery.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-020.png&lt;br /&gt;
Image:Fgfs-screen-016.png&lt;br /&gt;
Image:Fgfs-screen-012.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
=== '''''The Good old Cessna Citation X''''' ===&lt;br /&gt;
I hope to do a monthly review of a specific aircraft. I can't guarantee that I will get to do it every month though because I do have other stuff to attend to.&lt;br /&gt;
&lt;br /&gt;
The [[Cessna Citation X]] is by far one of my favourite little planes! Its reaction time is quite quick. The rudder control is very responsive, even the slightest move of your rudder pedals or the mouse and the aircraft's rudder moves. It accelerates quite fast down the runway, building up momentum and then, you lift your joystick up slightly and the nose lifts up just like you want it to. &lt;br /&gt;
&lt;br /&gt;
Regarding the animations, they are extraordinary. They function quite well like for example the flaps, spoilers or the landing gear. The cockpit is quite well designed and has a lot of instruments, just like a real Citation would. &lt;br /&gt;
&lt;br /&gt;
It has a tutorial system built in for people wanting to fly one. '''''This was the first jet plane that I could actually land properly in.''''' It also has several nice camera views, including views from the passenger seats. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Cockpit.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 1.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 2.png&lt;br /&gt;
Image:Cessna Citation X - Screenshot 2.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Recommendation:'''&lt;br /&gt;
&lt;br /&gt;
I would recommend this plane to people who have already flown planes like the [[Cessna C172P]] or the [[Piper J3 Cub]] and want to progress into Jet aviation. This is a GREAT little starter plane to get you going.&lt;br /&gt;
&lt;br /&gt;
This has to be one of the best planes that I have ever used in FlightGear!&lt;br /&gt;
&lt;br /&gt;
Thanks for reading! :D&lt;br /&gt;
&lt;br /&gt;
'''''Review By: Vinura'''''&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
===New articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===New aircraft articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
  categoryRoot=Aircraft&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===Most popular newsletters===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=hot&lt;br /&gt;
  count=5&lt;br /&gt;
  categoryRoot=FlightGear Newsletter&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on youtube ===&lt;br /&gt;
&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
==== FlyingClub Mayday 1 ====&lt;br /&gt;
The FGFC '''&amp;quot;Mayday 1: Manitoba Rescue&amp;quot;''' operation was held April 2nd, 2011 at CYAV, Winnipeg/St.Andrews, with seven pilots participating. The scenario stated two of Manitoba's major rivers were flooding, and people were stranded along both, so STOL and helicopter pilots were mustered at CYAV, received assignments from ATC, planned their flights, and notified ATC when they were ready to proceed. A total of twenty missions were assigned, sixteen of which were successfully completed in the space of three hours.&lt;br /&gt;
&lt;br /&gt;
The scenario was based around the idea that pilots should have basic skills in addition to merely flying with an autopilot, and was designed to test both their actual flying ability by not having airports at their destinations, and providing no actual navigational data beyond a map or two. They were required to map their routes in territory unknown to them, then fly those routes in their chosen aircraft, land, report in, then return to CYAV to complete a &amp;quot;cycle.&amp;quot; Points were awarded for cycle completion, and points deducted for aircraft crashes. FG Seg faults were not penalized.&lt;br /&gt;
&lt;br /&gt;
Comments back about the operation from pilots have so far been positive. Watch the [http://www.flightgear.org/forums/viewforum.php?f=10&amp;amp;sid=381d9860a9183d143cd2fa8aee16099d Multiplayer Forums] for the next one; there will be one, but at this writing, it has not yet been decided. &lt;br /&gt;
&lt;br /&gt;
* [[FlightGear Flying Club]]&lt;br /&gt;
* [http://flightgearfans.wordpress.com/about/ FGFC WordPress Site ]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=10&amp;amp;t=11551 Mayday 1 Forum Pages]&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common misconception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The [[OpenRadar]] project is looking for a new maintainer.&lt;br /&gt;
* The [[FGFSPM]] (FlightGear Package Manager) is looking for a new maintainer.&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
*...that you can fly backwards in a UFO? While holding the brake button down on your joystick or keyboard, increase engine throttle and you should start to fly backwards. A short video can be seen at [http://www.youtube.com/watch?v=F7U1bsO7g-EYouTube]&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2011 04]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31129</id>
		<title>FlightGear Newsletter April 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31129"/>
		<updated>2011-04-20T07:24:06Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Did you know */  Added an adjective - short - Changed some grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
''We would like to emphasize that the monthly newsletter can not live without the contributions of FlightGear users and developers. Everyone with a wiki account (free to register) can edit the newsletter and every contribution is welcome. So if you know about any FlightGear related projects such as for example updated scenery or aircraft, please do feel invited to add such news to the newsletter.''&lt;br /&gt;
&lt;br /&gt;
== Development news ==&lt;br /&gt;
=== Atmospheric scattering shader ===&lt;br /&gt;
Zan has been working very hard on an experimental atmospheric scattering [[shader]]. The shaders makes use of [http://sponeil.net/ Sean O'Neil's algorithm]. Altough there are some issues with the shader, it looks like it will have a promising future!&lt;br /&gt;
&lt;br /&gt;
=== Doctor Who Fans ===&lt;br /&gt;
[[Image:Tardis colour.png|thumb|Doctor Who TARDIS]]&lt;br /&gt;
Vinura has started work on developing a [http://en.wikipedia.org/wiki/TARDIS#The_Doctor.27s_TARDIS Doctor Who TARDIS] for FlightGear. The exterior model is almost complete in SketchUp. Click [http://www.flightgear.org/forums/viewtopic.php?f=4&amp;amp;t=11738 here] for the development thread.&lt;br /&gt;
&lt;br /&gt;
Currently, I still need to get the TARDIS colours right as I am only allowed to use 'Named Colours' from Google SketchUp as they can't claim copyright on colours.&lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
=== New instruments ===&lt;br /&gt;
The [[Boeing 777-200ER]]'s chronometer has been moved to the generic instruments directory (&amp;lt;tt&amp;gt;Aircraft/Instruments-3d/chronometer&amp;lt;/tt&amp;gt;). This allows aircraft developers to easily implement this clock in their aircraft. All related Nasal code was included in the model xml file, so there's really just one file to be linked to! Some aircraft already make use of this clock, including the [[Boeing 747-400]] and [[Boeing 757-200|757-200]]. &lt;br /&gt;
&lt;br /&gt;
There are several advantages in moving instruments to the generic directoy, some of which are:&lt;br /&gt;
* Easy to be re-used in other aircraft, all you need to do is link to (and position) the model and on some instruments link to a Nasal file.&lt;br /&gt;
* If someone extents the functionality of a generic instrument, it will be automatically extended in all the aircraft that use it.&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
=== Vostok-1 ===&lt;br /&gt;
[[Image:Vostok-1-Carrier-News.png|thumb|Vostok-1 Carrier]]&lt;br /&gt;
[[Image:Vostok-1-News.png|thumb|Vostok-1 Spacecraft]]&lt;br /&gt;
[[Image:Vostok-1-Interior-News.png|thumb|Vostok-1 Interior]]&lt;br /&gt;
To celebrate Yury Gagarin's historical flight, [[Vostok-1]] carrier and spacecraft were added to FlightGear. In heavy development still, it already allows full orbital flight from lift-off to landing, making it perform the first spaceflight in FlightGear. &lt;br /&gt;
&lt;br /&gt;
Things that make it possible:&lt;br /&gt;
*[[JSBSim]] centrifugal force addition made the whole flight available.&lt;br /&gt;
*JSBSim property driven point masses, tanks and engines, and aerodynamic coefficients implementation allow stages changing. Each single stage of the flight has an independent mass scheme, propulsion system, and aerodynamics reactions, so simulation is more or less realistic.&lt;br /&gt;
*Datcom+ with &amp;quot;little wing&amp;quot; approach resolves carrier and spacecraft aerodynamics accurately enough to make flights on real fuel and oxidizer capacities with real g forces, orbit and deorbit paths. &lt;br /&gt;
*[[FlightGear Newsletter April 2011#Atmospheric scattering shader|Zan's shader]] makes the earth look pretty enough from high altitudes.&lt;br /&gt;
*FG improvement shifted practical flight ceiling from 80 to 160 kilometers.&lt;br /&gt;
&lt;br /&gt;
In real life, the first human spaceflight was fully automated. In FlightGear, instead controls are completely manual to make it interesting, and to make you understand how it really works.&lt;br /&gt;
&lt;br /&gt;
Authors and developers, since orbital flight is possible in FlightGear from now on, you are invited to make a FlightGear driven Mercury-Atlas project. Low earth orbit flights can be more exact and eyecandy in FlightGear than in any current simulator. And you can be sure it will be free for you and users in any case.&lt;br /&gt;
&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
[[Image:Fgfs-screen-072.png|thumb|Airbus A320]]&lt;br /&gt;
[[Image:Fgfs-screen-089.png|thumb|Boeing 767]]&lt;br /&gt;
Some [http://liveries.flightgear.org/airlines.php?id=231 SriLankan Airlines] liveries have been made by Vinura for the Boeing 767 and Airbus A320.&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
&lt;br /&gt;
=== New scenery ===&lt;br /&gt;
New third-party scenery for the USA's Pacific Northwest (Seattle and Portland, OR) and Rio de Janeiro is now available for download at http://www.stattosoftware.com/flightgear&lt;br /&gt;
&lt;br /&gt;
=== New Buildings ===&lt;br /&gt;
Once again, there are new Eastern Asian buildings !&lt;br /&gt;
&lt;br /&gt;
* Saigon Center - Ho Chi Minh City - Vietnam&lt;br /&gt;
* Mode Gakuen Coccoon Tower - Tokyo - Japan&lt;br /&gt;
* Trade Tower - Seoul - South Korea&lt;br /&gt;
* Koryo Hotel - Pyongyang - North Korea&lt;br /&gt;
* The Center - Hong Kong - China&lt;br /&gt;
* Central Plaza - Hong Kong - China&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
The generic Concourse C at KDEN was recently replaced with a much better, realistic working model featuring animated jetways. Please enjoy.&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
SriLankan Airlines livery on an Airbus A320 taken at dusk.&lt;br /&gt;
&lt;br /&gt;
[[File:Fgfs-screen-085.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
Departing from Brisbane International Airport and heading towards Sydney International Airport at a heading of about 203, you will come across some beautiful scenery.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-020.png&lt;br /&gt;
Image:Fgfs-screen-016.png&lt;br /&gt;
Image:Fgfs-screen-012.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
=== '''''The Good old Cessna Citation X''''' ===&lt;br /&gt;
I hope to do a monthly review of a specific aircraft. I can't guarantee that I will get to do it every month though because I do have other stuff to attend to.&lt;br /&gt;
&lt;br /&gt;
The [[Cessna Citation X]] is by far one of my favourite little planes! Its reaction time is quite quick. The rudder control is very responsive, even the slightest move of your rudder pedals or the mouse and the aircraft's rudder moves. It accelerates quite fast down the runway, building up momentum and then, you lift your joystick up slightly and the nose lifts up just like you want it to. &lt;br /&gt;
&lt;br /&gt;
Regarding the animations, they are extraordinary. They function quite well like for example the flaps, spoilers or the landing gear. The cockpit is quite well designed and has a lot of instruments, just like a real Citation would. &lt;br /&gt;
&lt;br /&gt;
It has a tutorial system built in for people wanting to fly one. '''''This was the first jet plane that I could actually land properly in.''''' It also has several nice camera views, including views from the passenger seats. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Cockpit.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 1.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 2.png&lt;br /&gt;
Image:Cessna Citation X - Screenshot 2.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Recommendation:'''&lt;br /&gt;
&lt;br /&gt;
I would recommend this plane to people who have already flown planes like the [[Cessna C172P]] or the [[Piper J3 Cub]] and want to progress into Jet aviation. This is a GREAT little starter plane to get you going.&lt;br /&gt;
&lt;br /&gt;
This has to be one of the best planes that I have ever used in FlightGear!&lt;br /&gt;
&lt;br /&gt;
Thanks for reading! :D&lt;br /&gt;
&lt;br /&gt;
'''''Review By: Vinura'''''&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
===New articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===New aircraft articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
  categoryRoot=Aircraft&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===Most popular newsletters===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=hot&lt;br /&gt;
  count=5&lt;br /&gt;
  categoryRoot=FlightGear Newsletter&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on youtube ===&lt;br /&gt;
&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
==== FlyingClub Mayday 1 ====&lt;br /&gt;
The FGFC '''&amp;quot;Mayday 1: Manitoba Rescue&amp;quot;''' operation was held April 2nd, 2011 at CYAV, Winnipeg/St.Andrews, with seven pilots participating. The scenario stated two of Manitoba's major rivers were flooding, and people were stranded along both, so STOL and helicopter pilots were mustered at CYAV, received assignments from ATC, planned their flights, and notified ATC when they were ready to proceed. A total of twenty missions were assigned, sixteen of which were successfully completed in the space of three hours.&lt;br /&gt;
&lt;br /&gt;
The scenario was based around the idea that pilots should have basic skills in addition to merely flying with an autopilot, and was designed to test both their actual flying ability by not having airports at their destinations, and providing no actual navigational data beyond a map or two. They were required to map their routes in territory unknown to them, then fly those routes in their chosen aircraft, land, report in, then return to CYAV to complete a &amp;quot;cycle.&amp;quot; Points were awarded for cycle completion, and points deducted for aircraft crashes. FG Seg faults were not penalized.&lt;br /&gt;
&lt;br /&gt;
Comments back about the operation from pilots have so far been positive. Watch the [http://www.flightgear.org/forums/viewforum.php?f=10&amp;amp;sid=381d9860a9183d143cd2fa8aee16099d Multiplayer Forums] for the next one; there will be one, but at this writing, it has not yet been decided. &lt;br /&gt;
&lt;br /&gt;
* [[FlightGear Flying Club]]&lt;br /&gt;
* [http://flightgearfans.wordpress.com/about/ FGFC WordPress Site ]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=10&amp;amp;t=11551 Mayday 1 Forum Pages]&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common misconception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The [[OpenRadar]] project is looking for a new maintainer.&lt;br /&gt;
* The [[FGFSPM]] (FlightGear Package Manager) is looking for a new maintainer.&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
*...that you can fly backwards in a UFO? While holding the brake button down on your joystick or keyboard, increase engine throttle and you should start to fly backwards. A short video can be seen at [http://www.youtube.com/watch?v=F7U1bsO7g-EYouTube]&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2011 04]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31124</id>
		<title>FlightGear Newsletter April 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31124"/>
		<updated>2011-04-20T07:19:41Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Development news */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
''We would like to emphasize that the monthly newsletter can not live without the contributions of FlightGear users and developers. Everyone with a wiki account (free to register) can edit the newsletter and every contribution is welcome. So if you know about any FlightGear related projects such as for example updated scenery or aircraft, please do feel invited to add such news to the newsletter.''&lt;br /&gt;
&lt;br /&gt;
== Development news ==&lt;br /&gt;
=== Atmospheric scattering shader ===&lt;br /&gt;
Zan has been working very hard on an experimental atmospheric scattering [[shader]]. The shaders makes use of [http://sponeil.net/ Sean O'Neil's algorithm]. Altough there are some issues with the shader, it looks like it will have a promising future!&lt;br /&gt;
&lt;br /&gt;
=== Doctor Who Fans ===&lt;br /&gt;
[[Image:Tardis colour.png|thumb|Doctor Who TARDIS]]&lt;br /&gt;
Vinura has started work on developing a [http://en.wikipedia.org/wiki/TARDIS#The_Doctor.27s_TARDIS Doctor Who TARDIS] for FlightGear. The exterior model is almost complete in SketchUp. Click [http://www.flightgear.org/forums/viewtopic.php?f=4&amp;amp;t=11738 here] for the development thread.&lt;br /&gt;
&lt;br /&gt;
Currently, I still need to get the TARDIS colours right as I am only allowed to use 'Named Colours' from Google SketchUp as they can't claim copyright on colours.&lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
=== New instruments ===&lt;br /&gt;
The [[Boeing 777-200ER]]'s chronometer has been moved to the generic instruments directory (&amp;lt;tt&amp;gt;Aircraft/Instruments-3d/chronometer&amp;lt;/tt&amp;gt;). This allows aircraft developers to easily implement this clock in their aircraft. All related Nasal code was included in the model xml file, so there's really just one file to be linked to! Some aircraft already make use of this clock, including the [[Boeing 747-400]] and [[Boeing 757-200|757-200]]. &lt;br /&gt;
&lt;br /&gt;
There are several advantages in moving instruments to the generic directoy, some of which are:&lt;br /&gt;
* Easy to be re-used in other aircraft, all you need to do is link to (and position) the model and on some instruments link to a Nasal file.&lt;br /&gt;
* If someone extents the functionality of a generic instrument, it will be automatically extended in all the aircraft that use it.&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
=== Vostok-1 ===&lt;br /&gt;
[[Image:Vostok-1-Carrier-News.png|thumb|Vostok-1 Carrier]]&lt;br /&gt;
[[Image:Vostok-1-News.png|thumb|Vostok-1 Spacecraft]]&lt;br /&gt;
[[Image:Vostok-1-Interior-News.png|thumb|Vostok-1 Interior]]&lt;br /&gt;
To celebrate Yury Gagarin's historical flight, [[Vostok-1]] carrier and spacecraft were added to FlightGear. In heavy development still, it already allows full orbital flight from lift-off to landing, making it perform the first spaceflight in FlightGear. &lt;br /&gt;
&lt;br /&gt;
Things that make it possible:&lt;br /&gt;
*[[JSBSim]] centrifugal force addition made the whole flight available.&lt;br /&gt;
*JSBSim property driven point masses, tanks and engines, and aerodynamic coefficients implementation allow stages changing. Each single stage of the flight has an independent mass scheme, propulsion system, and aerodynamics reactions, so simulation is more or less realistic.&lt;br /&gt;
*Datcom+ with &amp;quot;little wing&amp;quot; approach resolves carrier and spacecraft aerodynamics accurately enough to make flights on real fuel and oxidizer capacities with real g forces, orbit and deorbit paths. &lt;br /&gt;
*[[FlightGear Newsletter April 2011#Atmospheric scattering shader|Zan's shader]] makes the earth look pretty enough from high altitudes.&lt;br /&gt;
*FG improvement shifted practical flight ceiling from 80 to 160 kilometers.&lt;br /&gt;
&lt;br /&gt;
In real life, the first human spaceflight was fully automated. In FlightGear, instead controls are completely manual to make it interesting, and to make you understand how it really works.&lt;br /&gt;
&lt;br /&gt;
Authors and developers, since orbital flight is possible in FlightGear from now on, you are invited to make a FlightGear driven Mercury-Atlas project. Low earth orbit flights can be more exact and eyecandy in FlightGear than in any current simulator. And you can be sure it will be free for you and users in any case.&lt;br /&gt;
&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
[[Image:Fgfs-screen-072.png|thumb|Airbus A320]]&lt;br /&gt;
[[Image:Fgfs-screen-089.png|thumb|Boeing 767]]&lt;br /&gt;
Some [http://liveries.flightgear.org/airlines.php?id=231 SriLankan Airlines] liveries have been made by Vinura for the Boeing 767 and Airbus A320.&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
&lt;br /&gt;
=== New scenery ===&lt;br /&gt;
New third-party scenery for the USA's Pacific Northwest (Seattle and Portland, OR) and Rio de Janeiro is now available for download at http://www.stattosoftware.com/flightgear&lt;br /&gt;
&lt;br /&gt;
=== New Buildings ===&lt;br /&gt;
Once again, there are new Eastern Asian buildings !&lt;br /&gt;
&lt;br /&gt;
* Saigon Center - Ho Chi Minh City - Vietnam&lt;br /&gt;
* Mode Gakuen Coccoon Tower - Tokyo - Japan&lt;br /&gt;
* Trade Tower - Seoul - South Korea&lt;br /&gt;
* Koryo Hotel - Pyongyang - North Korea&lt;br /&gt;
* The Center - Hong Kong - China&lt;br /&gt;
* Central Plaza - Hong Kong - China&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
The generic Concourse C at KDEN was recently replaced with a much better, realistic working model featuring animated jetways. Please enjoy.&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
SriLankan Airlines livery on an Airbus A320 taken at dusk.&lt;br /&gt;
&lt;br /&gt;
[[File:Fgfs-screen-085.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
Departing from Brisbane International Airport and heading towards Sydney International Airport at a heading of about 203, you will come across some beautiful scenery.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-020.png&lt;br /&gt;
Image:Fgfs-screen-016.png&lt;br /&gt;
Image:Fgfs-screen-012.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
=== '''''The Good old Cessna Citation X''''' ===&lt;br /&gt;
I hope to do a monthly review of a specific aircraft. I can't guarantee that I will get to do it every month though because I do have other stuff to attend to.&lt;br /&gt;
&lt;br /&gt;
The [[Cessna Citation X]] is by far one of my favourite little planes! Its reaction time is quite quick. The rudder control is very responsive, even the slightest move of your rudder pedals or the mouse and the aircraft's rudder moves. It accelerates quite fast down the runway, building up momentum and then, you lift your joystick up slightly and the nose lifts up just like you want it to. &lt;br /&gt;
&lt;br /&gt;
Regarding the animations, they are extraordinary. They function quite well like for example the flaps, spoilers or the landing gear. The cockpit is quite well designed and has a lot of instruments, just like a real Citation would. &lt;br /&gt;
&lt;br /&gt;
It has a tutorial system built in for people wanting to fly one. '''''This was the first jet plane that I could actually land properly in.''''' It also has several nice camera views, including views from the passenger seats. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Cockpit.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 1.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 2.png&lt;br /&gt;
Image:Cessna Citation X - Screenshot 2.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Recommendation:'''&lt;br /&gt;
&lt;br /&gt;
I would recommend this plane to people who have already flown planes like the [[Cessna C172P]] or the [[Piper J3 Cub]] and want to progress into Jet aviation. This is a GREAT little starter plane to get you going.&lt;br /&gt;
&lt;br /&gt;
This has to be one of the best planes that I have ever used in FlightGear!&lt;br /&gt;
&lt;br /&gt;
Thanks for reading! :D&lt;br /&gt;
&lt;br /&gt;
'''''Review By: Vinura'''''&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
===New articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===New aircraft articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
  categoryRoot=Aircraft&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===Most popular newsletters===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=hot&lt;br /&gt;
  count=5&lt;br /&gt;
  categoryRoot=FlightGear Newsletter&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on youtube ===&lt;br /&gt;
&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
==== FlyingClub Mayday 1 ====&lt;br /&gt;
The FGFC '''&amp;quot;Mayday 1: Manitoba Rescue&amp;quot;''' operation was held April 2nd, 2011 at CYAV, Winnipeg/St.Andrews, with seven pilots participating. The scenario stated two of Manitoba's major rivers were flooding, and people were stranded along both, so STOL and helicopter pilots were mustered at CYAV, received assignments from ATC, planned their flights, and notified ATC when they were ready to proceed. A total of twenty missions were assigned, sixteen of which were successfully completed in the space of three hours.&lt;br /&gt;
&lt;br /&gt;
The scenario was based around the idea that pilots should have basic skills in addition to merely flying with an autopilot, and was designed to test both their actual flying ability by not having airports at their destinations, and providing no actual navigational data beyond a map or two. They were required to map their routes in territory unknown to them, then fly those routes in their chosen aircraft, land, report in, then return to CYAV to complete a &amp;quot;cycle.&amp;quot; Points were awarded for cycle completion, and points deducted for aircraft crashes. FG Seg faults were not penalized.&lt;br /&gt;
&lt;br /&gt;
Comments back about the operation from pilots have so far been positive. Watch the [http://www.flightgear.org/forums/viewforum.php?f=10&amp;amp;sid=381d9860a9183d143cd2fa8aee16099d Multiplayer Forums] for the next one; there will be one, but at this writing, it has not yet been decided. &lt;br /&gt;
&lt;br /&gt;
* [[FlightGear Flying Club]]&lt;br /&gt;
* [http://flightgearfans.wordpress.com/about/ FGFC WordPress Site ]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=10&amp;amp;t=11551 Mayday 1 Forum Pages]&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common misconception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The [[OpenRadar]] project is looking for a new maintainer.&lt;br /&gt;
* The [[FGFSPM]] (FlightGear Package Manager) is looking for a new maintainer.&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
*...that you can fly backwards in a UFO? While holding the brake button down on your joystick or keyboard, increase engine throttle and you should start to fly backwards. A video is to be seen at [http://www.youtube.com/watch?v=F7U1bsO7g-EYouTube]&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2011 04]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31123</id>
		<title>FlightGear Newsletter April 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31123"/>
		<updated>2011-04-20T07:15:26Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Doctor Who Fans */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
''We would like to emphasize that the monthly newsletter can not live without the contributions of FlightGear users and developers. Everyone with a wiki account (free to register) can edit the newsletter and every contribution is welcome. So if you know about any FlightGear related projects such as for example updated scenery or aircraft, please do feel invited to add such news to the newsletter.''&lt;br /&gt;
&lt;br /&gt;
== Development news ==&lt;br /&gt;
=== Atmospheric scattering shader ===&lt;br /&gt;
Zan has been working very hard on an experimental atmospheric scattering [[shader]]. The shaders makes use of [http://sponeil.net/ Sean O'Neil's algorithm]. Altough there are some issues with the shader, it looks like it will have a promising future!&lt;br /&gt;
&lt;br /&gt;
==== Doctor Who Fans ====&lt;br /&gt;
[[Image:Tardis colour.png|thumb|Doctor Who TARDIS]]&lt;br /&gt;
Vinura has started work on developing a [http://en.wikipedia.org/wiki/TARDIS#The_Doctor.27s_TARDIS Doctor Who TARDIS] for FlightGear. The exterior model is almost complete in SketchUp. Click [http://www.flightgear.org/forums/viewtopic.php?f=4&amp;amp;t=11738 here] for the development thread.&lt;br /&gt;
&lt;br /&gt;
Currently, I still need to get the TARDIS colours right as I am only allowed to use 'Named Colours' from Google SketchUp as they can't claim copyright on colours.&lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
=== New instruments ===&lt;br /&gt;
The [[Boeing 777-200ER]]'s chronometer has been moved to the generic instruments directory (&amp;lt;tt&amp;gt;Aircraft/Instruments-3d/chronometer&amp;lt;/tt&amp;gt;). This allows aircraft developers to easily implement this clock in their aircraft. All related Nasal code was included in the model xml file, so there's really just one file to be linked to! Some aircraft already make use of this clock, including the [[Boeing 747-400]] and [[Boeing 757-200|757-200]]. &lt;br /&gt;
&lt;br /&gt;
There are several advantages in moving instruments to the generic directoy, some of which are:&lt;br /&gt;
* Easy to be re-used in other aircraft, all you need to do is link to (and position) the model and on some instruments link to a Nasal file.&lt;br /&gt;
* If someone extents the functionality of a generic instrument, it will be automatically extended in all the aircraft that use it.&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
=== Vostok-1 ===&lt;br /&gt;
[[Image:Vostok-1-Carrier-News.png|thumb|Vostok-1 Carrier]]&lt;br /&gt;
[[Image:Vostok-1-News.png|thumb|Vostok-1 Spacecraft]]&lt;br /&gt;
[[Image:Vostok-1-Interior-News.png|thumb|Vostok-1 Interior]]&lt;br /&gt;
To celebrate Yury Gagarin's historical flight, [[Vostok-1]] carrier and spacecraft were added to FlightGear. In heavy development still, it already allows full orbital flight from lift-off to landing, making it perform the first spaceflight in FlightGear. &lt;br /&gt;
&lt;br /&gt;
Things that make it possible:&lt;br /&gt;
*[[JSBSim]] centrifugal force addition made the whole flight available.&lt;br /&gt;
*JSBSim property driven point masses, tanks and engines, and aerodynamic coefficients implementation allow stages changing. Each single stage of the flight has an independent mass scheme, propulsion system, and aerodynamics reactions, so simulation is more or less realistic.&lt;br /&gt;
*Datcom+ with &amp;quot;little wing&amp;quot; approach resolves carrier and spacecraft aerodynamics accurately enough to make flights on real fuel and oxidizer capacities with real g forces, orbit and deorbit paths. &lt;br /&gt;
*[[FlightGear Newsletter April 2011#Atmospheric scattering shader|Zan's shader]] makes the earth look pretty enough from high altitudes.&lt;br /&gt;
*FG improvement shifted practical flight ceiling from 80 to 160 kilometers.&lt;br /&gt;
&lt;br /&gt;
In real life, the first human spaceflight was fully automated. In FlightGear, instead controls are completely manual to make it interesting, and to make you understand how it really works.&lt;br /&gt;
&lt;br /&gt;
Authors and developers, since orbital flight is possible in FlightGear from now on, you are invited to make a FlightGear driven Mercury-Atlas project. Low earth orbit flights can be more exact and eyecandy in FlightGear than in any current simulator. And you can be sure it will be free for you and users in any case.&lt;br /&gt;
&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
[[Image:Fgfs-screen-072.png|thumb|Airbus A320]]&lt;br /&gt;
[[Image:Fgfs-screen-089.png|thumb|Boeing 767]]&lt;br /&gt;
Some [http://liveries.flightgear.org/airlines.php?id=231 SriLankan Airlines] liveries have been made by Vinura for the Boeing 767 and Airbus A320.&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
&lt;br /&gt;
=== New scenery ===&lt;br /&gt;
New third-party scenery for the USA's Pacific Northwest (Seattle and Portland, OR) and Rio de Janeiro is now available for download at http://www.stattosoftware.com/flightgear&lt;br /&gt;
&lt;br /&gt;
=== New Buildings ===&lt;br /&gt;
Once again, there are new Eastern Asian buildings !&lt;br /&gt;
&lt;br /&gt;
* Saigon Center - Ho Chi Minh City - Vietnam&lt;br /&gt;
* Mode Gakuen Coccoon Tower - Tokyo - Japan&lt;br /&gt;
* Trade Tower - Seoul - South Korea&lt;br /&gt;
* Koryo Hotel - Pyongyang - North Korea&lt;br /&gt;
* The Center - Hong Kong - China&lt;br /&gt;
* Central Plaza - Hong Kong - China&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
The generic Concourse C at KDEN was recently replaced with a much better, realistic working model featuring animated jetways. Please enjoy.&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
SriLankan Airlines livery on an Airbus A320 taken at dusk.&lt;br /&gt;
&lt;br /&gt;
[[File:Fgfs-screen-085.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
Departing from Brisbane International Airport and heading towards Sydney International Airport at a heading of about 203, you will come across some beautiful scenery.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-020.png&lt;br /&gt;
Image:Fgfs-screen-016.png&lt;br /&gt;
Image:Fgfs-screen-012.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
=== '''''The Good old Cessna Citation X''''' ===&lt;br /&gt;
I hope to do a monthly review of a specific aircraft. I can't guarantee that I will get to do it every month though because I do have other stuff to attend to.&lt;br /&gt;
&lt;br /&gt;
The [[Cessna Citation X]] is by far one of my favourite little planes! Its reaction time is quite quick. The rudder control is very responsive, even the slightest move of your rudder pedals or the mouse and the aircraft's rudder moves. It accelerates quite fast down the runway, building up momentum and then, you lift your joystick up slightly and the nose lifts up just like you want it to. &lt;br /&gt;
&lt;br /&gt;
Regarding the animations, they are extraordinary. They function quite well like for example the flaps, spoilers or the landing gear. The cockpit is quite well designed and has a lot of instruments, just like a real Citation would. &lt;br /&gt;
&lt;br /&gt;
It has a tutorial system built in for people wanting to fly one. '''''This was the first jet plane that I could actually land properly in.''''' It also has several nice camera views, including views from the passenger seats. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Cockpit.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 1.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 2.png&lt;br /&gt;
Image:Cessna Citation X - Screenshot 2.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Recommendation:'''&lt;br /&gt;
&lt;br /&gt;
I would recommend this plane to people who have already flown planes like the [[Cessna C172P]] or the [[Piper J3 Cub]] and want to progress into Jet aviation. This is a GREAT little starter plane to get you going.&lt;br /&gt;
&lt;br /&gt;
This has to be one of the best planes that I have ever used in FlightGear!&lt;br /&gt;
&lt;br /&gt;
Thanks for reading! :D&lt;br /&gt;
&lt;br /&gt;
'''''Review By: Vinura'''''&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
===New articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===New aircraft articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
  categoryRoot=Aircraft&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===Most popular newsletters===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=hot&lt;br /&gt;
  count=5&lt;br /&gt;
  categoryRoot=FlightGear Newsletter&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on youtube ===&lt;br /&gt;
&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
==== FlyingClub Mayday 1 ====&lt;br /&gt;
The FGFC '''&amp;quot;Mayday 1: Manitoba Rescue&amp;quot;''' operation was held April 2nd, 2011 at CYAV, Winnipeg/St.Andrews, with seven pilots participating. The scenario stated two of Manitoba's major rivers were flooding, and people were stranded along both, so STOL and helicopter pilots were mustered at CYAV, received assignments from ATC, planned their flights, and notified ATC when they were ready to proceed. A total of twenty missions were assigned, sixteen of which were successfully completed in the space of three hours.&lt;br /&gt;
&lt;br /&gt;
The scenario was based around the idea that pilots should have basic skills in addition to merely flying with an autopilot, and was designed to test both their actual flying ability by not having airports at their destinations, and providing no actual navigational data beyond a map or two. They were required to map their routes in territory unknown to them, then fly those routes in their chosen aircraft, land, report in, then return to CYAV to complete a &amp;quot;cycle.&amp;quot; Points were awarded for cycle completion, and points deducted for aircraft crashes. FG Seg faults were not penalized.&lt;br /&gt;
&lt;br /&gt;
Comments back about the operation from pilots have so far been positive. Watch the [http://www.flightgear.org/forums/viewforum.php?f=10&amp;amp;sid=381d9860a9183d143cd2fa8aee16099d Multiplayer Forums] for the next one; there will be one, but at this writing, it has not yet been decided. &lt;br /&gt;
&lt;br /&gt;
* [[FlightGear Flying Club]]&lt;br /&gt;
* [http://flightgearfans.wordpress.com/about/ FGFC WordPress Site ]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=10&amp;amp;t=11551 Mayday 1 Forum Pages]&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common misconception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The [[OpenRadar]] project is looking for a new maintainer.&lt;br /&gt;
* The [[FGFSPM]] (FlightGear Package Manager) is looking for a new maintainer.&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
*...that you can fly backwards in a UFO? While holding the brake button down on your joystick or keyboard, increase engine throttle and you should start to fly backwards. A video is to be seen at [http://www.youtube.com/watch?v=F7U1bsO7g-EYouTube]&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2011 04]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Tardis_colour.png&amp;diff=31122</id>
		<title>File:Tardis colour.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Tardis_colour.png&amp;diff=31122"/>
		<updated>2011-04-20T07:11:50Z</updated>

		<summary type="html">&lt;p&gt;Vin: TARDIS - Added Colour&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TARDIS - Added Colour&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Animated_jetways_(Type_1)&amp;diff=31092</id>
		<title>Howto:Animated jetways (Type 1)</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Animated_jetways_(Type_1)&amp;diff=31092"/>
		<updated>2011-04-18T04:31:50Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* In the simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:777jetwaybeaf.jpg|thumb|right|300px|Before and after; jetways connecting to a [[Boeing 777-200]]]]&lt;br /&gt;
[[File:KLAS_jetways.png|thumb|right|300px|Animated jetway connected to a [[Boeing 737-300]] at Las Vegas McCarran International Airport (KLAS)]]&lt;br /&gt;
[[File:Movjetway-night.jpg|thumb|right|300px|Jetways at Reno International Airport (KRNO) lighting up during the night]]&lt;br /&gt;
[[File:Animatedjetway1.jpg|thumb|right|270px|A gate with one animated jetway; note the style, the details, and the level walking passage]]&lt;br /&gt;
&lt;br /&gt;
'''Animated jetways''' are dynamic jetway models that connect to your aircraft when you are pulled up at the gate. While [[FlightGear]]'s jetways are primitive compared to those of X plane or Microsoft Flight Simulator, they are still fun to use and an improvement compared to static jetways. This article describes how to use the jetways and implement them in various aspects of FlightGear.&lt;br /&gt;
&lt;br /&gt;
= Usage =&lt;br /&gt;
&lt;br /&gt;
== Obtaining the models ==&lt;br /&gt;
&lt;br /&gt;
For FlightGear versions [[FlightGear 2.0.0|2.0.0]] and below, the jetway models are not distributed with the [[$FG_ROOT|base package]]. They can be downloaded directly from the [[FlightGear Scenery Database]], or you can use [[TerraSync]] to fetch them.&lt;br /&gt;
&lt;br /&gt;
=== Downloading from the database ===&lt;br /&gt;
&lt;br /&gt;
Download the following models and extract the archives in &amp;lt;tt&amp;gt;[[$FG_ROOT]]/Models/Airport&amp;lt;/tt&amp;gt;:&lt;br /&gt;
* [http://scenemodels.flightgear.org/modeledit.php?id=1827 jetway-movable.xml]&lt;br /&gt;
* [http://scenemodels.flightgear.org/modeledit.php?id=1833 jetway-movable-2.xml]&lt;br /&gt;
* [http://scenemodels.flightgear.org/modeledit.php?id=1834 jetway-movable-3.xml]&lt;br /&gt;
&lt;br /&gt;
=== Downloading through TerraSync ===&lt;br /&gt;
&lt;br /&gt;
Simply run TerraSync anywhere, and the models will be downloaded. However, for FlightGear 2.0.0 and below, you need to add one extra option to load them. For command-line users, add the following switch:&lt;br /&gt;
&lt;br /&gt;
 --prop:/sim/paths/use-custom-scenery-data=true&lt;br /&gt;
&lt;br /&gt;
If you are using [[FlightGear Launch Control]] (the launcher distributed with the Windows version of FlightGear), click the &amp;quot;Advanced&amp;quot; button at the last page, click the &amp;quot;Properties&amp;quot; tab, click &amp;quot;New&amp;quot;, set the property name to &amp;lt;tt&amp;gt;/sim/paths/use-custom-scenery-data&amp;lt;/tt&amp;gt;, and set the value to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== In the simulation ==&lt;br /&gt;
&lt;br /&gt;
Fly (or spawn) to an airport with animated jetways in an aircraft with the required positioning information. Currently, the following airports implement animated jetways:&lt;br /&gt;
&lt;br /&gt;
* Ted Stevens Anchorage International Airport ('''PANC''') (TerraSync-only)&lt;br /&gt;
* Las Vegas McCarran International Airport ('''KLAS''') (TerraSync-only)&lt;br /&gt;
* Reno International Airport ('''KRNO''') (TerraSync-only)&lt;br /&gt;
* San Francisco International Airport ('''KSFO''') Vinura is currently working on support for this airport,&lt;br /&gt;
&lt;br /&gt;
The following aircraft are animated jetway-capable:&lt;br /&gt;
&lt;br /&gt;
* [[Airbus A320 Family]]&lt;br /&gt;
* [[Airbus A380]] ([[FlightGear Git|Git]] version only)&lt;br /&gt;
* [[Boeing 757-200]] (Git version only)&lt;br /&gt;
* [[Boeing 747-400]] (Git version only)&lt;br /&gt;
* [[Boeing 787|Boeing 787-8]] (Git version only)&lt;br /&gt;
* [[Bombardier CRJ-200LR]] (Git version only)&lt;br /&gt;
* [[Bombardier CRJ-900]]&lt;br /&gt;
&lt;br /&gt;
Pull up to a gate, and determine for sure if the jetway is animated. To do this, press Ctrl-C. It is animated if its polygons are outlined in yellow. ''This holds true for all clickable objects, not just animated jetways!''&lt;br /&gt;
&lt;br /&gt;
Now align your aircraft so that the nose gear is centered on the marking line and is directly over the &amp;quot;T&amp;quot; at the end of it. Click the jetway; if your aircraft does not include the required positioning information, you'll get a tooltip informing you that the jetway cannot be extended. Otherwise, the jetway should begin to position itself and eventually connect to your aircraft.&lt;br /&gt;
&lt;br /&gt;
If there are multiple jetways at the gate, each jetway is operated independently. (You'll have to click each jetway to extend/retract them.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Video disabled pending improvements --&amp;gt;&lt;br /&gt;
&amp;lt;!--=== Video ===&lt;br /&gt;
&lt;br /&gt;
Here is a tutorial made by Vin on how to use the Animated Jetways;&lt;br /&gt;
&lt;br /&gt;
PLEASE NOTE: The videos weren't made by the same person or people that created the Animated Jetways for FlightGear or the same person or people that created this page. The videos were created by Vin, a different user.&lt;br /&gt;
&lt;br /&gt;
You should use the properties window when setting up this;&lt;br /&gt;
&lt;br /&gt;
--prop:/sim/paths/use-custom-scenery-data=true&lt;br /&gt;
&lt;br /&gt;
Part 1;&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|uM_rWZorGoQ}}&lt;br /&gt;
&lt;br /&gt;
Part 2;&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|0NykU9q_jpc}}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== In aircraft ==&lt;br /&gt;
&lt;br /&gt;
''This article assumes you have basic knowledge on how to use 3d modelling software.''&lt;br /&gt;
&lt;br /&gt;
Open up your favorite 3d modelling program (the author prefers [[Blender]]), and load any one of the jetway models (&amp;lt;tt&amp;gt;jetway-movable.ac&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;jetway-movable-2.ac&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;jetway-movable-3.ac&amp;lt;/tt&amp;gt;). Now import your aircraft model, and move it around so that it is &amp;quot;parked&amp;quot; at the gate. After that, simply get the coordinates of the bottom of the door the jetway should connect to.&lt;br /&gt;
&lt;br /&gt;
[[File:Animated-jetway-tutorial.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now add the following XML code in your &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file, outside the &amp;lt;tt&amp;gt;&amp;amp;lt;sim&amp;amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;aircraft&amp;gt;&lt;br /&gt;
		&amp;lt;door n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;x-m&amp;gt;POSITION_X&amp;lt;/x-m&amp;gt;&lt;br /&gt;
			&amp;lt;y-m&amp;gt;POSITION_Y&amp;lt;/y-m&amp;gt;&lt;br /&gt;
			&amp;lt;z-m&amp;gt;POSITION_Z&amp;lt;/z-m&amp;gt;&lt;br /&gt;
		&amp;lt;/door&amp;gt;&lt;br /&gt;
		&amp;lt;jetway-hood-deg type=&amp;quot;double&amp;quot;&amp;gt;HOOD_DEG&amp;lt;/jetway-hood-deg&amp;gt;&lt;br /&gt;
	&amp;lt;/aircraft&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;tt&amp;gt;POSITION_X&amp;lt;/tt&amp;gt; is the x coordinate of the door, &amp;lt;tt&amp;gt;POSITION_Y&amp;lt;/tt&amp;gt; is the y coordinate of the door, &amp;lt;tt&amp;gt;POSITION_Z&amp;lt;/tt&amp;gt; is the z coordinate of the door, and &amp;lt;tt&amp;gt;HOOD_DEG&amp;lt;/tt&amp;gt; is the amount to rotate the jetway hood. Generally, this should be 2-3 degrees.&lt;br /&gt;
&lt;br /&gt;
In the case of 2 or 3 jetways, simply find the coordinates of the other doors in the same manner and add more &amp;lt;tt&amp;gt;&amp;amp;lt;door&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. This example is from the [[Airbus A320 Family|Airbus A321]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;aircraft&amp;gt;&lt;br /&gt;
		&amp;lt;door n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;x-m&amp;gt;16.582&amp;lt;/x-m&amp;gt;&lt;br /&gt;
			&amp;lt;y-m&amp;gt;9.702&amp;lt;/y-m&amp;gt;&lt;br /&gt;
			&amp;lt;z-m&amp;gt;3.642&amp;lt;/z-m&amp;gt;&lt;br /&gt;
		&amp;lt;/door&amp;gt;&lt;br /&gt;
		&amp;lt;door n=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;x-m&amp;gt;25.468&amp;lt;/x-m&amp;gt;&lt;br /&gt;
			&amp;lt;y-m&amp;gt;9.693&amp;lt;/y-m&amp;gt;&lt;br /&gt;
			&amp;lt;z-m&amp;gt;3.642&amp;lt;/z-m&amp;gt;&lt;br /&gt;
		&amp;lt;/door&amp;gt;&lt;br /&gt;
		&amp;lt;jetway-hood-deg type=&amp;quot;double&amp;quot;&amp;gt;3&amp;lt;/jetway-hood-deg&amp;gt;&lt;br /&gt;
	&amp;lt;/aircraft&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's it! Your aircraft is now animated jetway-capable!&lt;br /&gt;
&lt;br /&gt;
== In scenery ==&lt;br /&gt;
&lt;br /&gt;
=== Placing in airports ===&lt;br /&gt;
&lt;br /&gt;
Simply place a &amp;lt;tt&amp;gt;Models/Airport/jetway-movable.xml&amp;lt;/tt&amp;gt; (single jetway), &amp;lt;tt&amp;gt;Models/Airport/jetway-movable-2.xml&amp;lt;/tt&amp;gt; (double jetway), or &amp;lt;tt&amp;gt;Models/Airport/jetway-movable-3.xml&amp;lt;/tt&amp;gt; (triple jetway) wherever you want- note that the model origins are always at the rotunda of jetway 1. &lt;br /&gt;
&lt;br /&gt;
=== Making your own animated jetways ===&lt;br /&gt;
&lt;br /&gt;
Just copy the XML file used in one of the default jetway models, and then use your own model. However, if you don't want to mess around with any Nasal code, it is important that '''the object names and the positions of the jetway parts are the same as those in the default jetway models'''.&lt;br /&gt;
&lt;br /&gt;
If you insist on changing around those locations, find the following lines in the Nasal code:&lt;br /&gt;
&lt;br /&gt;
  var xm = getprop(&amp;quot;/aircraft/door[0]/x-m&amp;quot;);&lt;br /&gt;
  var ym = getprop(&amp;quot;/aircraft/door[0]/y-m&amp;quot;) - 2.65;&lt;br /&gt;
  var zm = getprop(&amp;quot;/aircraft/door[0]/z-m&amp;quot;) - 3.752;&lt;br /&gt;
&lt;br /&gt;
Change the &amp;lt;tt&amp;gt;- 2.65&amp;lt;/tt&amp;gt; to the distance from the jetway's center to the edge of the entrance connecting to the aircraft, and the &amp;lt;tt&amp;gt;- 3.752&amp;lt;/tt&amp;gt; to the height of the bottom of the jetway entrance.&lt;br /&gt;
&lt;br /&gt;
= How it works =&lt;br /&gt;
&lt;br /&gt;
Animated jetways work by making use of several rotate animations and a lot of [[Nasal]] scripting. All Nasal code for the system is contained in this pick animation. In the case of multiple jetways, one such animation is used per jetway.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;animation&amp;gt;&lt;br /&gt;
		&amp;lt;type&amp;gt;pick&amp;lt;/type&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Rotunda1&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel1Rotunda&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel1&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel2&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel3&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Rotunda2&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Entrance&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Hood&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;&lt;br /&gt;
			&amp;lt;button&amp;gt;0&amp;lt;/button&amp;gt;&lt;br /&gt;
			&amp;lt;repeatable type=&amp;quot;bool&amp;quot;&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
			&amp;lt;binding&amp;gt;&lt;br /&gt;
				&amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
				&amp;lt;!-- Nasal pick code --&amp;gt;&lt;br /&gt;
				&amp;lt;script&amp;gt;&amp;lt;![CDATA[&lt;br /&gt;
				 ...&lt;br /&gt;
				]]&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
			&amp;lt;/binding&amp;gt;&lt;br /&gt;
		&amp;lt;/action&amp;gt;&lt;br /&gt;
	&amp;lt;/animation&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the actual nasal code. Documentation for each section follows.&lt;br /&gt;
&lt;br /&gt;
 if (props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;) == nil)&lt;br /&gt;
  {&lt;br /&gt;
  props.globals.initNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;, 0, &amp;quot;BOOL&amp;quot;);&lt;br /&gt;
  setprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;, 0);&lt;br /&gt;
  }&lt;br /&gt;
 if (props.globals.getNode(&amp;quot;/scenery/airport/jetway-movable-debug&amp;quot;) == nil)&lt;br /&gt;
  {&lt;br /&gt;
  props.globals.initNode(&amp;quot;/scenery/airport/jetway-movable-debug&amp;quot;, 0, &amp;quot;BOOL&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Here, we check if the jetway properties in the property tree exist. First, we check for &amp;lt;tt&amp;gt;/scenery/airport/jetway[X]/extended&amp;lt;/tt&amp;gt;. If it exists, we assume that the necessary properties are already up and running. Otherwise, we intialize the &amp;lt;tt&amp;gt;extended&amp;lt;/tt&amp;gt; and the &amp;lt;tt&amp;gt;position-norm&amp;lt;/tt&amp;gt; properties. Then, we check for &amp;lt;tt&amp;gt;/scenery/airport/jetway-movable-debug&amp;lt;/tt&amp;gt;- this is a special property that, if set true, will cause the script to output debugging information. If this property does not exist, we also initialize it.&lt;br /&gt;
&lt;br /&gt;
 # nasal interpolation function - returns a value based on a set interpolation table, like the &amp;lt;interpolate&amp;gt; feature of XML animations&lt;br /&gt;
 # takes an array with sub-arrays, like&lt;br /&gt;
 # [[&amp;lt;ind&amp;gt;, &amp;lt;dep&amp;gt;], [&amp;lt;ind&amp;gt;, &amp;lt;dep&amp;gt;]]&lt;br /&gt;
 var interpolateTable = func(table, value)&lt;br /&gt;
  {&lt;br /&gt;
  ...&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
This is a custom function that computes a value based on an interpolation table (the kind found in [[animations]] and [[autopilot]] filters). Since it's difficult to explain how it works and it's not totally necessary to understand this function to understand the animated jetway system, I'll skip over it.&lt;br /&gt;
&lt;br /&gt;
 var xtranslate = nil;&lt;br /&gt;
 var yrotate = nil;&lt;br /&gt;
 var zrotate = nil;&lt;br /&gt;
 var hoodrotate = nil;&lt;br /&gt;
 &lt;br /&gt;
 if (props.globals.getNode(&amp;quot;/aircraft/door[0]/x-m&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/door[0]/y-m&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/door[0]/z-m&amp;quot;) != nil)&lt;br /&gt;
  {&lt;br /&gt;
  var xm = getprop(&amp;quot;/aircraft/door[0]/x-m&amp;quot;);&lt;br /&gt;
  var ym = getprop(&amp;quot;/aircraft/door[0]/y-m&amp;quot;) - 2.65;&lt;br /&gt;
  var zm = getprop(&amp;quot;/aircraft/door[0]/z-m&amp;quot;) - 3.752;&lt;br /&gt;
&lt;br /&gt;
We create our variables, &amp;lt;tt&amp;gt;xtranslate&amp;lt;/tt&amp;gt;- the length, in meters, to extend the jetway, &amp;lt;tt&amp;gt;yrotate&amp;lt;/tt&amp;gt;- the amount, in degrees, to rotate the jetway along the Y axis, &amp;lt;tt&amp;gt;zrotate&amp;lt;/tt&amp;gt;- the amount, in degrees, to rotate the jetway along the Z axis, and &amp;lt;tt&amp;gt;hoodrotate&amp;lt;/tt&amp;gt;- the amount, in degrees, to rotate the jetway hood along the X axis.&lt;br /&gt;
&lt;br /&gt;
If the user's aircraft happens to have support for the latest animated jetway implementation, we initialize variables &amp;lt;tt&amp;gt;xm&amp;lt;/tt&amp;gt;- the relative location of the aircraft's door, in meters, along the X axis, &amp;lt;tt&amp;gt;ym&amp;lt;/tt&amp;gt;- the relative location of the aircraft's door, in meters, along the Y axis, &amp;lt;tt&amp;gt;zm&amp;lt;/tt&amp;gt;- the relative location of the aircraft's door, in meters, along the Z axis. In the case of jetway #1, the Y and the Z axises need to be offset for the initial position of jetway. The X axis also needs to be offset, but we will factor this in later- some calculations require a &amp;quot;clean&amp;quot; X value without any modification.&lt;br /&gt;
&lt;br /&gt;
Now we'll calculate the actual values of the &amp;lt;tt&amp;gt;xtranslate&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;yrotate&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zrotate&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;hoodrotate&amp;lt;/tt&amp;gt; variables from earlier. For this purpose we will consider the jetway and the aircraft door as parts of right triangles.&lt;br /&gt;
&lt;br /&gt;
[[File:Animated-jetway-diagram1.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[File:Animated-jetway-diagram2.jpg]]&lt;br /&gt;
&lt;br /&gt;
  # calculate the extension length using the Pythagorean Theorem (c = sqrt(a^2 + b^2))&lt;br /&gt;
  xtranslate = math.sqrt(xm * xm + ym * ym) - 19.536;&lt;br /&gt;
&lt;br /&gt;
Refer to the first diagram. Calculating &amp;lt;tt&amp;gt;xtranslate&amp;lt;/tt&amp;gt; is relatively simple- all it takes is a simple Pythagorean equation (''a² + b² = c²'', or ''c = √(a² + b²)''). We factor in the length of the jetway in its initial position by subtracting 19.536 meters from our result.&lt;br /&gt;
&lt;br /&gt;
  # calculate the rotation angle along the Y axis&lt;br /&gt;
  yrotate = math.atan2(zm / xm, 1) * R2D;&lt;br /&gt;
&lt;br /&gt;
For this section, refer to the second diagram. Here is where that trigonometry you learned back in school becomes useful! Here, we calculate &amp;lt;tt&amp;gt;yrotate&amp;lt;/tt&amp;gt; using the tangent of angle ''x'', or ''b / a''. Then we use the mathematical function atan. Nasal doesn't have atan implemented in its &amp;lt;tt&amp;gt;math&amp;lt;/tt&amp;gt; object, so we use &amp;lt;tt&amp;gt;math.atan2(b / a, 1)&amp;lt;/tt&amp;gt; instead. All trigonometric calculations in [[FlightGear]] are done in radians, so we multiply our result by &amp;lt;tt&amp;gt;R2D&amp;lt;/tt&amp;gt; (pi / 180) to convert to degrees.&lt;br /&gt;
&lt;br /&gt;
''Author's note: In hindsight, perhaps the A320 wasn't the best example aircraft to use, since the height difference between the jetway and the door is fairly small.''&lt;br /&gt;
&lt;br /&gt;
  # calculate the rotation angle along the Z axis&lt;br /&gt;
  zrotate = math.atan2(ym / xm, 1) * R2D;&lt;br /&gt;
&lt;br /&gt;
Refer to the first diagram for this section. Here, we calculate &amp;lt;tt&amp;gt;zrotate&amp;lt;/tt&amp;gt;, again using atan.&lt;br /&gt;
&lt;br /&gt;
  # hood rotation angle is predefined&lt;br /&gt;
  hoodrotate = getprop(&amp;quot;/aircraft/jetway-hood-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The hood rotation amount is predefined by the aircraft.&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
 # old system (legacy support)&lt;br /&gt;
 elsif (props.globals.getNode(&amp;quot;/aircraft/jetway-pos/x-tra&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/jetway-pos/y-rot&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/jetway-pos/z-rot&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/jetway-pos/hood-rot&amp;quot;) != nil)&lt;br /&gt;
  {&lt;br /&gt;
  # rotation angles and extension lengths are predefined&lt;br /&gt;
  xtranslate = getprop(&amp;quot;/aircraft/jetway-pos/x-tra&amp;quot;);&lt;br /&gt;
  yrotate = getprop(&amp;quot;/aircraft/jetway-pos/y-rot&amp;quot;);&lt;br /&gt;
  zrotate = getprop(&amp;quot;/aircraft/jetway-pos/z-rot&amp;quot;);&lt;br /&gt;
  hoodrotate = getprop(&amp;quot;/aircraft/jetway-pos/hood-rot&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And finally, if the user's aircraft supports the old system instead of the latest, we fall back to the properties used in the old way that thout shall not mention.&lt;br /&gt;
&lt;br /&gt;
 var xtranslaterate = 0.5;&lt;br /&gt;
 var xtranslatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.2, 0.5],&lt;br /&gt;
   [0.6, 0.5],&lt;br /&gt;
   [0.8, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var yrotaterate = 1;&lt;br /&gt;
 var yrotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.4, 0.7],&lt;br /&gt;
   [0.7, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var zrotaterate = 1;&lt;br /&gt;
 var zrotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.2, 0.0],&lt;br /&gt;
   [0.6, 0.7],&lt;br /&gt;
   [0.8, 0.7],&lt;br /&gt;
   [0.9, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var zentrancerotaterate = 5;&lt;br /&gt;
 var zentrancerotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.5, 0.0],&lt;br /&gt;
   [0.6, 0.7],&lt;br /&gt;
   [0.8, 0.7],&lt;br /&gt;
   [0.9, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var hoodrotaterate = 1;&lt;br /&gt;
 var hoodrotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.9, 0.0],&lt;br /&gt;
   [1,0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
These are the interpolation tables used by the earlier function. The extension and rotation rates are also defined here, in meters per second and degrees per second.&lt;br /&gt;
&lt;br /&gt;
 if (xtranslate != nil and yrotate != nil and zrotate != nil and hoodrotate != nil)&lt;br /&gt;
  {&lt;br /&gt;
  var length = math.abs(xtranslate / xtranslaterate) + math.abs(yrotate / yrotaterate) + math.abs(zrotate / zrotaterate) + math.abs(zrotate / zentrancerotaterate) + math.abs(hoodrotate / hoodrotaterate);&lt;br /&gt;
  &lt;br /&gt;
  if (props.globals.getNode(&amp;quot;/scenery/airport/jetway-movable-debug&amp;quot;).getBoolValue())&lt;br /&gt;
   {&lt;br /&gt;
   print(&amp;quot;Animated jetway debug information:&amp;quot;);&lt;br /&gt;
   print(&amp;quot;----------------------------------&amp;quot;);&lt;br /&gt;
   print(&amp;quot;x-translation-m: &amp;quot; ~ xtranslate);&lt;br /&gt;
   print(&amp;quot;y-rotation-deg: &amp;quot; ~ yrotate);&lt;br /&gt;
   print(&amp;quot;z-rotation-deg: &amp;quot; ~ zrotate);&lt;br /&gt;
   print(&amp;quot;hood-x-rotation-deg: &amp;quot; ~ hoodrotate);&lt;br /&gt;
   print(&amp;quot;&amp;quot;);&lt;br /&gt;
   print(&amp;quot;Total animation time: &amp;quot; ~ length ~ &amp;quot; seconds&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
If all our variables exist (they were assigned a non-nil value somewhere along the line), we calculate the total animation length for a full extension and print debug information if &amp;lt;tt&amp;gt;/scenery/airport/jetway-movable-debug&amp;lt;/tt&amp;gt; is set to true.&lt;br /&gt;
&lt;br /&gt;
  if (!props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
   {&lt;br /&gt;
   props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).setBoolValue(1);&lt;br /&gt;
   interpolate(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;,&lt;br /&gt;
     1, -getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;) + 1 * length&lt;br /&gt;
   );&lt;br /&gt;
   gui.popupTip(&amp;quot;Extending jetway.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   var loop = func&lt;br /&gt;
    {&lt;br /&gt;
    var position = getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/x-translation-m&amp;quot;, interpolateTable(xtranslatetable, position) * xtranslate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/y-rotation-deg&amp;quot;, interpolateTable(yrotatetable, position) * yrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-rotation-deg&amp;quot;, interpolateTable(zrotatetable, position) * zrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-entrance-rotation-deg&amp;quot;, interpolateTable(zentrancerotatetable, position) * zrotate) ;&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/hood-x-rotation-deg&amp;quot;, interpolateTable(hoodrotatetable, position) * hoodrotate);&lt;br /&gt;
    &lt;br /&gt;
    if (position &amp;lt; 1 and props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
     {&lt;br /&gt;
     settimer(loop, 0);&lt;br /&gt;
     }&lt;br /&gt;
    };&lt;br /&gt;
   loop();&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;extended&amp;lt;/tt&amp;gt; is set to true, we retract the jetway. We use the native &amp;lt;tt&amp;gt;interpolate()&amp;lt;/tt&amp;gt; function to interpolate the &amp;lt;tt&amp;gt;position-norm&amp;lt;/tt&amp;gt; property, and then create a loop that modifies the animation properties as the jetway extends/retracts.&lt;br /&gt;
&lt;br /&gt;
  elsif (props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
   {&lt;br /&gt;
   props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).setBoolValue(0);&lt;br /&gt;
   interpolate(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;,&lt;br /&gt;
     0, getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;) * length&lt;br /&gt;
    );&lt;br /&gt;
   gui.popupTip(&amp;quot;Retracting jetway.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   var loop = func&lt;br /&gt;
    {&lt;br /&gt;
    var position = getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/x-translation-m&amp;quot;, interpolateTable(xtranslatetable, position) * xtranslate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/y-rotation-deg&amp;quot;, interpolateTable(yrotatetable, position) * yrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-rotation-deg&amp;quot;, interpolateTable(zrotatetable, position) * zrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-entrance-rotation-deg&amp;quot;, interpolateTable(zentrancerotatetable, position) * zrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/hood-x-rotation-deg&amp;quot;, interpolateTable(hoodrotatetable, position) * hoodrotate);&lt;br /&gt;
    &lt;br /&gt;
    if (position &amp;gt; 0 and !props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
     {&lt;br /&gt;
     settimer(loop, 0);&lt;br /&gt;
     }&lt;br /&gt;
    };&lt;br /&gt;
   loop();&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;extended&amp;lt;/tt&amp;gt; is set to false, we do the exact same thing in reverse.&lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 else&lt;br /&gt;
  {&lt;br /&gt;
  gui.popupTip(&amp;quot;Cannot extend jetway: Your aircraft does not define the required positioning information.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
If our variables ''are'' nil, then we assume that the aircraft lacks animated jetway support and notify the user that this is the case.&lt;br /&gt;
&lt;br /&gt;
= Limitations =&lt;br /&gt;
&lt;br /&gt;
* The jetway does not &amp;quot;know&amp;quot; the position of the aircraft, but rather moves to a predefined location relative to the jetway, unlike in X plane or Microsoft Flight Simulator where the jetways extend to an aircraft (mostly) precisely regardless of its location.&lt;br /&gt;
* Separate gates cannot move independently- you may notice that all jetways extend when you click one of them.&lt;br /&gt;
&lt;br /&gt;
= External links =&lt;br /&gt;
&lt;br /&gt;
* [http://tinypic.com/player.php?v=ajul44&amp;amp;s=4 Video showcasing the animation]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?t=8728 Development thread]&lt;br /&gt;
&lt;br /&gt;
[[Category:Scenery]]&lt;br /&gt;
[[Category:Scenery enhancement]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Animated_jetways_(Type_1)&amp;diff=31084</id>
		<title>Howto:Animated jetways (Type 1)</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Animated_jetways_(Type_1)&amp;diff=31084"/>
		<updated>2011-04-17T08:26:40Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* In the simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:777jetwaybeaf.jpg|thumb|right|300px|Before and after; jetways connecting to a [[Boeing 777-200]]]]&lt;br /&gt;
[[File:KLAS_jetways.png|thumb|right|300px|Animated jetway connected to a [[Boeing 737-300]] at Las Vegas McCarran International Airport (KLAS)]]&lt;br /&gt;
[[File:Movjetway-night.jpg|thumb|right|300px|Jetways at Reno International Airport (KRNO) lighting up during the night]]&lt;br /&gt;
[[File:Animatedjetway1.jpg|thumb|right|270px|A gate with one animated jetway; note the style, the details, and the level walking passage]]&lt;br /&gt;
&lt;br /&gt;
'''Animated jetways''' are dynamic jetway models that connect to your aircraft when you are pulled up at the gate. While [[FlightGear]]'s jetways are primitive compared to those of X plane or Microsoft Flight Simulator, they are still fun to use and an improvement compared to static jetways. This article describes how to use the jetways and implement them in various aspects of FlightGear.&lt;br /&gt;
&lt;br /&gt;
= Usage =&lt;br /&gt;
&lt;br /&gt;
== Obtaining the models ==&lt;br /&gt;
&lt;br /&gt;
For FlightGear versions [[FlightGear 2.0.0|2.0.0]] and below, the jetway models are not distributed with the [[$FG_ROOT|base package]]. They can be downloaded directly from the [[FlightGear Scenery Database]], or you can use [[TerraSync]] to fetch them.&lt;br /&gt;
&lt;br /&gt;
=== Downloading from the database ===&lt;br /&gt;
&lt;br /&gt;
Download the following models and extract the archives in &amp;lt;tt&amp;gt;[[$FG_ROOT]]/Models/Airport&amp;lt;/tt&amp;gt;:&lt;br /&gt;
* [http://scenemodels.flightgear.org/modeledit.php?id=1827 jetway-movable.xml]&lt;br /&gt;
* [http://scenemodels.flightgear.org/modeledit.php?id=1833 jetway-movable-2.xml]&lt;br /&gt;
* [http://scenemodels.flightgear.org/modeledit.php?id=1834 jetway-movable-3.xml]&lt;br /&gt;
&lt;br /&gt;
=== Downloading through TerraSync ===&lt;br /&gt;
&lt;br /&gt;
Simply run TerraSync anywhere, and the models will be downloaded. However, for FlightGear 2.0.0 and below, you need to add one extra option to load them. For command-line users, add the following switch:&lt;br /&gt;
&lt;br /&gt;
 --prop:/sim/paths/use-custom-scenery-data=true&lt;br /&gt;
&lt;br /&gt;
If you are using [[FlightGear Launch Control]] (the launcher distributed with the Windows version of FlightGear), click the &amp;quot;Advanced&amp;quot; button at the last page, click the &amp;quot;Properties&amp;quot; tab, click &amp;quot;New&amp;quot;, set the property name to &amp;lt;tt&amp;gt;/sim/paths/use-custom-scenery-data&amp;lt;/tt&amp;gt;, and set the value to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== In the simulation ==&lt;br /&gt;
&lt;br /&gt;
Fly (or spawn) to an airport with animated jetways in an aircraft with the required positioning information. Currently, the following airports implement animated jetways:&lt;br /&gt;
&lt;br /&gt;
* Ted Stevens Anchorage International Airport ('''PANC''') (TerraSync-only)&lt;br /&gt;
* Las Vegas McCarran International Airport ('''KLAS''') (TerraSync-only)&lt;br /&gt;
* Reno International Airport ('''KRNO''') (TerraSync-only)&lt;br /&gt;
&lt;br /&gt;
The following aircraft are animated jetway-capable:&lt;br /&gt;
&lt;br /&gt;
* [[Airbus A320 Family]]&lt;br /&gt;
* [[Airbus A380]] ([[FlightGear Git|Git]] version only)&lt;br /&gt;
* [[Boeing 757-200]] (Git version only)&lt;br /&gt;
* [[Boeing 747]] (Git version only)&lt;br /&gt;
* [[Boeing 787|Boeing 787-8]] (Git version only)&lt;br /&gt;
* [[Bombardier CRJ-200LR]] (Git version only)&lt;br /&gt;
* [[Bombardier CRJ-900]]&lt;br /&gt;
&lt;br /&gt;
Pull up to a gate, and determine for sure if the jetway is animated. To do this, press Ctrl-C. It is animated if its polygons are outlined in yellow. ''This holds true for all clickable objects, not just animated jetways!''&lt;br /&gt;
&lt;br /&gt;
Now align your aircraft so that the nose gear is centered on the marking line and is directly over the &amp;quot;T&amp;quot; at the end of it. Click the jetway; if your aircraft does not include the required positioning information, you'll get a tooltip informing you that the jetway cannot be extended. Otherwise, the jetway should begin to position itself and eventually connect to your aircraft.&lt;br /&gt;
&lt;br /&gt;
If there are multiple jetways at the gate, each jetway is operated independently. (You'll have to click each jetway to extend/retract them.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Video disabled pending improvements --&amp;gt;&lt;br /&gt;
&amp;lt;!--=== Video ===&lt;br /&gt;
&lt;br /&gt;
Here is a tutorial made by Vin on how to use the Animated Jetways;&lt;br /&gt;
&lt;br /&gt;
PLEASE NOTE: The videos weren't made by the same person or people that created the Animated Jetways for FlightGear or the same person or people that created this page. The videos were created by Vin, a different user.&lt;br /&gt;
&lt;br /&gt;
You should use the properties window when setting up this;&lt;br /&gt;
&lt;br /&gt;
--prop:/sim/paths/use-custom-scenery-data=true&lt;br /&gt;
&lt;br /&gt;
Part 1;&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|uM_rWZorGoQ}}&lt;br /&gt;
&lt;br /&gt;
Part 2;&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|0NykU9q_jpc}}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Implementation =&lt;br /&gt;
&lt;br /&gt;
== In aircraft ==&lt;br /&gt;
&lt;br /&gt;
''This article assumes you have basic knowledge on how to use 3d modelling software.''&lt;br /&gt;
&lt;br /&gt;
Open up your favorite 3d modelling program (the author prefers [[Blender]]), and load any one of the jetway models (&amp;lt;tt&amp;gt;jetway-movable.ac&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;jetway-movable-2.ac&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;jetway-movable-3.ac&amp;lt;/tt&amp;gt;). Now import your aircraft model, and move it around so that it is &amp;quot;parked&amp;quot; at the gate. After that, simply get the coordinates of the bottom of the door the jetway should connect to.&lt;br /&gt;
&lt;br /&gt;
[[File:Animated-jetway-tutorial.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now add the following XML code in your &amp;lt;tt&amp;gt;-set.xml&amp;lt;/tt&amp;gt; file, outside the &amp;lt;tt&amp;gt;&amp;amp;lt;sim&amp;amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;aircraft&amp;gt;&lt;br /&gt;
		&amp;lt;door n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;x-m&amp;gt;POSITION_X&amp;lt;/x-m&amp;gt;&lt;br /&gt;
			&amp;lt;y-m&amp;gt;POSITION_Y&amp;lt;/y-m&amp;gt;&lt;br /&gt;
			&amp;lt;z-m&amp;gt;POSITION_Z&amp;lt;/z-m&amp;gt;&lt;br /&gt;
		&amp;lt;/door&amp;gt;&lt;br /&gt;
		&amp;lt;jetway-hood-deg type=&amp;quot;double&amp;quot;&amp;gt;HOOD_DEG&amp;lt;/jetway-hood-deg&amp;gt;&lt;br /&gt;
	&amp;lt;/aircraft&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;tt&amp;gt;POSITION_X&amp;lt;/tt&amp;gt; is the x coordinate of the door, &amp;lt;tt&amp;gt;POSITION_Y&amp;lt;/tt&amp;gt; is the y coordinate of the door, &amp;lt;tt&amp;gt;POSITION_Z&amp;lt;/tt&amp;gt; is the z coordinate of the door, and &amp;lt;tt&amp;gt;HOOD_DEG&amp;lt;/tt&amp;gt; is the amount to rotate the jetway hood. Generally, this should be 2-3 degrees.&lt;br /&gt;
&lt;br /&gt;
In the case of 2 or 3 jetways, simply find the coordinates of the other doors in the same manner and add more &amp;lt;tt&amp;gt;&amp;amp;lt;door&amp;amp;gt;&amp;lt;/tt&amp;gt; elements. This example is from the [[Airbus A320 Family|Airbus A321]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;aircraft&amp;gt;&lt;br /&gt;
		&amp;lt;door n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;x-m&amp;gt;16.582&amp;lt;/x-m&amp;gt;&lt;br /&gt;
			&amp;lt;y-m&amp;gt;9.702&amp;lt;/y-m&amp;gt;&lt;br /&gt;
			&amp;lt;z-m&amp;gt;3.642&amp;lt;/z-m&amp;gt;&lt;br /&gt;
		&amp;lt;/door&amp;gt;&lt;br /&gt;
		&amp;lt;door n=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
			&amp;lt;x-m&amp;gt;25.468&amp;lt;/x-m&amp;gt;&lt;br /&gt;
			&amp;lt;y-m&amp;gt;9.693&amp;lt;/y-m&amp;gt;&lt;br /&gt;
			&amp;lt;z-m&amp;gt;3.642&amp;lt;/z-m&amp;gt;&lt;br /&gt;
		&amp;lt;/door&amp;gt;&lt;br /&gt;
		&amp;lt;jetway-hood-deg type=&amp;quot;double&amp;quot;&amp;gt;3&amp;lt;/jetway-hood-deg&amp;gt;&lt;br /&gt;
	&amp;lt;/aircraft&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's it! Your aircraft is now animated jetway-capable!&lt;br /&gt;
&lt;br /&gt;
== In scenery ==&lt;br /&gt;
&lt;br /&gt;
=== Placing in airports ===&lt;br /&gt;
&lt;br /&gt;
Simply place a &amp;lt;tt&amp;gt;Models/Airport/jetway-movable.xml&amp;lt;/tt&amp;gt; (single jetway), &amp;lt;tt&amp;gt;Models/Airport/jetway-movable-2.xml&amp;lt;/tt&amp;gt; (double jetway), or &amp;lt;tt&amp;gt;Models/Airport/jetway-movable-3.xml&amp;lt;/tt&amp;gt; (triple jetway) wherever you want- note that the model origins are always at the rotunda of jetway 1. &lt;br /&gt;
&lt;br /&gt;
=== Making your own animated jetways ===&lt;br /&gt;
&lt;br /&gt;
Just copy the XML file used in one of the default jetway models, and then use your own model. However, if you don't want to mess around with any Nasal code, it is important that '''the object names and the positions of the jetway parts are the same as those in the default jetway models'''.&lt;br /&gt;
&lt;br /&gt;
If you insist on changing around those locations, find the following lines in the Nasal code:&lt;br /&gt;
&lt;br /&gt;
  var xm = getprop(&amp;quot;/aircraft/door[0]/x-m&amp;quot;);&lt;br /&gt;
  var ym = getprop(&amp;quot;/aircraft/door[0]/y-m&amp;quot;) - 2.65;&lt;br /&gt;
  var zm = getprop(&amp;quot;/aircraft/door[0]/z-m&amp;quot;) - 3.752;&lt;br /&gt;
&lt;br /&gt;
Change the &amp;lt;tt&amp;gt;- 2.65&amp;lt;/tt&amp;gt; to the distance from the jetway's center to the edge of the entrance connecting to the aircraft, and the &amp;lt;tt&amp;gt;- 3.752&amp;lt;/tt&amp;gt; to the height of the bottom of the jetway entrance.&lt;br /&gt;
&lt;br /&gt;
= How it works =&lt;br /&gt;
&lt;br /&gt;
Animated jetways work by making use of several rotate animations and a lot of [[Nasal]] scripting. All Nasal code for the system is contained in this pick animation. In the case of multiple jetways, one such animation is used per jetway.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight language=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;animation&amp;gt;&lt;br /&gt;
		&amp;lt;type&amp;gt;pick&amp;lt;/type&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Rotunda1&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel1Rotunda&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel1&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel2&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Tunnel3&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Rotunda2&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Entrance&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;object-name&amp;gt;Hood&amp;lt;/object-name&amp;gt;&lt;br /&gt;
		&amp;lt;action&amp;gt;&lt;br /&gt;
			&amp;lt;button&amp;gt;0&amp;lt;/button&amp;gt;&lt;br /&gt;
			&amp;lt;repeatable type=&amp;quot;bool&amp;quot;&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
			&amp;lt;binding&amp;gt;&lt;br /&gt;
				&amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
				&amp;lt;!-- Nasal pick code --&amp;gt;&lt;br /&gt;
				&amp;lt;script&amp;gt;&amp;lt;![CDATA[&lt;br /&gt;
				 ...&lt;br /&gt;
				]]&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
			&amp;lt;/binding&amp;gt;&lt;br /&gt;
		&amp;lt;/action&amp;gt;&lt;br /&gt;
	&amp;lt;/animation&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the actual nasal code. Documentation for each section follows.&lt;br /&gt;
&lt;br /&gt;
 if (props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;) == nil)&lt;br /&gt;
  {&lt;br /&gt;
  props.globals.initNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;, 0, &amp;quot;BOOL&amp;quot;);&lt;br /&gt;
  setprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;, 0);&lt;br /&gt;
  }&lt;br /&gt;
 if (props.globals.getNode(&amp;quot;/scenery/airport/jetway-movable-debug&amp;quot;) == nil)&lt;br /&gt;
  {&lt;br /&gt;
  props.globals.initNode(&amp;quot;/scenery/airport/jetway-movable-debug&amp;quot;, 0, &amp;quot;BOOL&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Here, we check if the jetway properties in the property tree exist. First, we check for &amp;lt;tt&amp;gt;/scenery/airport/jetway[X]/extended&amp;lt;/tt&amp;gt;. If it exists, we assume that the necessary properties are already up and running. Otherwise, we intialize the &amp;lt;tt&amp;gt;extended&amp;lt;/tt&amp;gt; and the &amp;lt;tt&amp;gt;position-norm&amp;lt;/tt&amp;gt; properties. Then, we check for &amp;lt;tt&amp;gt;/scenery/airport/jetway-movable-debug&amp;lt;/tt&amp;gt;- this is a special property that, if set true, will cause the script to output debugging information. If this property does not exist, we also initialize it.&lt;br /&gt;
&lt;br /&gt;
 # nasal interpolation function - returns a value based on a set interpolation table, like the &amp;lt;interpolate&amp;gt; feature of XML animations&lt;br /&gt;
 # takes an array with sub-arrays, like&lt;br /&gt;
 # [[&amp;lt;ind&amp;gt;, &amp;lt;dep&amp;gt;], [&amp;lt;ind&amp;gt;, &amp;lt;dep&amp;gt;]]&lt;br /&gt;
 var interpolateTable = func(table, value)&lt;br /&gt;
  {&lt;br /&gt;
  ...&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
This is a custom function that computes a value based on an interpolation table (the kind found in [[animations]] and [[autopilot]] filters). Since it's difficult to explain how it works and it's not totally necessary to understand this function to understand the animated jetway system, I'll skip over it.&lt;br /&gt;
&lt;br /&gt;
 var xtranslate = nil;&lt;br /&gt;
 var yrotate = nil;&lt;br /&gt;
 var zrotate = nil;&lt;br /&gt;
 var hoodrotate = nil;&lt;br /&gt;
 &lt;br /&gt;
 if (props.globals.getNode(&amp;quot;/aircraft/door[0]/x-m&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/door[0]/y-m&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/door[0]/z-m&amp;quot;) != nil)&lt;br /&gt;
  {&lt;br /&gt;
  var xm = getprop(&amp;quot;/aircraft/door[0]/x-m&amp;quot;);&lt;br /&gt;
  var ym = getprop(&amp;quot;/aircraft/door[0]/y-m&amp;quot;) - 2.65;&lt;br /&gt;
  var zm = getprop(&amp;quot;/aircraft/door[0]/z-m&amp;quot;) - 3.752;&lt;br /&gt;
&lt;br /&gt;
We create our variables, &amp;lt;tt&amp;gt;xtranslate&amp;lt;/tt&amp;gt;- the length, in meters, to extend the jetway, &amp;lt;tt&amp;gt;yrotate&amp;lt;/tt&amp;gt;- the amount, in degrees, to rotate the jetway along the Y axis, &amp;lt;tt&amp;gt;zrotate&amp;lt;/tt&amp;gt;- the amount, in degrees, to rotate the jetway along the Z axis, and &amp;lt;tt&amp;gt;hoodrotate&amp;lt;/tt&amp;gt;- the amount, in degrees, to rotate the jetway hood along the X axis.&lt;br /&gt;
&lt;br /&gt;
If the user's aircraft happens to have support for the latest animated jetway implementation, we initialize variables &amp;lt;tt&amp;gt;xm&amp;lt;/tt&amp;gt;- the relative location of the aircraft's door, in meters, along the X axis, &amp;lt;tt&amp;gt;ym&amp;lt;/tt&amp;gt;- the relative location of the aircraft's door, in meters, along the Y axis, &amp;lt;tt&amp;gt;zm&amp;lt;/tt&amp;gt;- the relative location of the aircraft's door, in meters, along the Z axis. In the case of jetway #1, the Y and the Z axises need to be offset for the initial position of jetway. The X axis also needs to be offset, but we will factor this in later- some calculations require a &amp;quot;clean&amp;quot; X value without any modification.&lt;br /&gt;
&lt;br /&gt;
Now we'll calculate the actual values of the &amp;lt;tt&amp;gt;xtranslate&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;yrotate&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zrotate&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;hoodrotate&amp;lt;/tt&amp;gt; variables from earlier. For this purpose we will consider the jetway and the aircraft door as parts of right triangles.&lt;br /&gt;
&lt;br /&gt;
[[File:Animated-jetway-diagram1.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[File:Animated-jetway-diagram2.jpg]]&lt;br /&gt;
&lt;br /&gt;
  # calculate the extension length using the Pythagorean Theorem (c = sqrt(a^2 + b^2))&lt;br /&gt;
  xtranslate = math.sqrt(xm * xm + ym * ym) - 19.536;&lt;br /&gt;
&lt;br /&gt;
Refer to the first diagram. Calculating &amp;lt;tt&amp;gt;xtranslate&amp;lt;/tt&amp;gt; is relatively simple- all it takes is a simple Pythagorean equation (''a² + b² = c²'', or ''c = √(a² + b²)''). We factor in the length of the jetway in its initial position by subtracting 19.536 meters from our result.&lt;br /&gt;
&lt;br /&gt;
  # calculate the rotation angle along the Y axis&lt;br /&gt;
  yrotate = math.atan2(zm / xm, 1) * R2D;&lt;br /&gt;
&lt;br /&gt;
For this section, refer to the second diagram. Here is where that trigonometry you learned back in school becomes useful! Here, we calculate &amp;lt;tt&amp;gt;yrotate&amp;lt;/tt&amp;gt; using the tangent of angle ''x'', or ''b / a''. Then we use the mathematical function atan. Nasal doesn't have atan implemented in its &amp;lt;tt&amp;gt;math&amp;lt;/tt&amp;gt; object, so we use &amp;lt;tt&amp;gt;math.atan2(b / a, 1)&amp;lt;/tt&amp;gt; instead. All trigonometric calculations in [[FlightGear]] are done in radians, so we multiply our result by &amp;lt;tt&amp;gt;R2D&amp;lt;/tt&amp;gt; (pi / 180) to convert to degrees.&lt;br /&gt;
&lt;br /&gt;
''Author's note: In hindsight, perhaps the A320 wasn't the best example aircraft to use, since the height difference between the jetway and the door is fairly small.''&lt;br /&gt;
&lt;br /&gt;
  # calculate the rotation angle along the Z axis&lt;br /&gt;
  zrotate = math.atan2(ym / xm, 1) * R2D;&lt;br /&gt;
&lt;br /&gt;
Refer to the first diagram for this section. Here, we calculate &amp;lt;tt&amp;gt;zrotate&amp;lt;/tt&amp;gt;, again using atan.&lt;br /&gt;
&lt;br /&gt;
  # hood rotation angle is predefined&lt;br /&gt;
  hoodrotate = getprop(&amp;quot;/aircraft/jetway-hood-deg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The hood rotation amount is predefined by the aircraft.&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
 # old system (legacy support)&lt;br /&gt;
 elsif (props.globals.getNode(&amp;quot;/aircraft/jetway-pos/x-tra&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/jetway-pos/y-rot&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/jetway-pos/z-rot&amp;quot;) != nil and props.globals.getNode(&amp;quot;/aircraft/jetway-pos/hood-rot&amp;quot;) != nil)&lt;br /&gt;
  {&lt;br /&gt;
  # rotation angles and extension lengths are predefined&lt;br /&gt;
  xtranslate = getprop(&amp;quot;/aircraft/jetway-pos/x-tra&amp;quot;);&lt;br /&gt;
  yrotate = getprop(&amp;quot;/aircraft/jetway-pos/y-rot&amp;quot;);&lt;br /&gt;
  zrotate = getprop(&amp;quot;/aircraft/jetway-pos/z-rot&amp;quot;);&lt;br /&gt;
  hoodrotate = getprop(&amp;quot;/aircraft/jetway-pos/hood-rot&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And finally, if the user's aircraft supports the old system instead of the latest, we fall back to the properties used in the old way that thout shall not mention.&lt;br /&gt;
&lt;br /&gt;
 var xtranslaterate = 0.5;&lt;br /&gt;
 var xtranslatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.2, 0.5],&lt;br /&gt;
   [0.6, 0.5],&lt;br /&gt;
   [0.8, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var yrotaterate = 1;&lt;br /&gt;
 var yrotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.4, 0.7],&lt;br /&gt;
   [0.7, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var zrotaterate = 1;&lt;br /&gt;
 var zrotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.2, 0.0],&lt;br /&gt;
   [0.6, 0.7],&lt;br /&gt;
   [0.8, 0.7],&lt;br /&gt;
   [0.9, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var zentrancerotaterate = 5;&lt;br /&gt;
 var zentrancerotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.5, 0.0],&lt;br /&gt;
   [0.6, 0.7],&lt;br /&gt;
   [0.8, 0.7],&lt;br /&gt;
   [0.9, 1.0],&lt;br /&gt;
   [1.0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
 &lt;br /&gt;
 var hoodrotaterate = 1;&lt;br /&gt;
 var hoodrotatetable = [&lt;br /&gt;
   [0.0, 0.0],&lt;br /&gt;
   [0.9, 0.0],&lt;br /&gt;
   [1,0, 1.0]&lt;br /&gt;
  ];&lt;br /&gt;
&lt;br /&gt;
These are the interpolation tables used by the earlier function. The extension and rotation rates are also defined here, in meters per second and degrees per second.&lt;br /&gt;
&lt;br /&gt;
 if (xtranslate != nil and yrotate != nil and zrotate != nil and hoodrotate != nil)&lt;br /&gt;
  {&lt;br /&gt;
  var length = math.abs(xtranslate / xtranslaterate) + math.abs(yrotate / yrotaterate) + math.abs(zrotate / zrotaterate) + math.abs(zrotate / zentrancerotaterate) + math.abs(hoodrotate / hoodrotaterate);&lt;br /&gt;
  &lt;br /&gt;
  if (props.globals.getNode(&amp;quot;/scenery/airport/jetway-movable-debug&amp;quot;).getBoolValue())&lt;br /&gt;
   {&lt;br /&gt;
   print(&amp;quot;Animated jetway debug information:&amp;quot;);&lt;br /&gt;
   print(&amp;quot;----------------------------------&amp;quot;);&lt;br /&gt;
   print(&amp;quot;x-translation-m: &amp;quot; ~ xtranslate);&lt;br /&gt;
   print(&amp;quot;y-rotation-deg: &amp;quot; ~ yrotate);&lt;br /&gt;
   print(&amp;quot;z-rotation-deg: &amp;quot; ~ zrotate);&lt;br /&gt;
   print(&amp;quot;hood-x-rotation-deg: &amp;quot; ~ hoodrotate);&lt;br /&gt;
   print(&amp;quot;&amp;quot;);&lt;br /&gt;
   print(&amp;quot;Total animation time: &amp;quot; ~ length ~ &amp;quot; seconds&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
If all our variables exist (they were assigned a non-nil value somewhere along the line), we calculate the total animation length for a full extension and print debug information if &amp;lt;tt&amp;gt;/scenery/airport/jetway-movable-debug&amp;lt;/tt&amp;gt; is set to true.&lt;br /&gt;
&lt;br /&gt;
  if (!props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
   {&lt;br /&gt;
   props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).setBoolValue(1);&lt;br /&gt;
   interpolate(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;,&lt;br /&gt;
     1, -getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;) + 1 * length&lt;br /&gt;
   );&lt;br /&gt;
   gui.popupTip(&amp;quot;Extending jetway.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   var loop = func&lt;br /&gt;
    {&lt;br /&gt;
    var position = getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/x-translation-m&amp;quot;, interpolateTable(xtranslatetable, position) * xtranslate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/y-rotation-deg&amp;quot;, interpolateTable(yrotatetable, position) * yrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-rotation-deg&amp;quot;, interpolateTable(zrotatetable, position) * zrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-entrance-rotation-deg&amp;quot;, interpolateTable(zentrancerotatetable, position) * zrotate) ;&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/hood-x-rotation-deg&amp;quot;, interpolateTable(hoodrotatetable, position) * hoodrotate);&lt;br /&gt;
    &lt;br /&gt;
    if (position &amp;lt; 1 and props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
     {&lt;br /&gt;
     settimer(loop, 0);&lt;br /&gt;
     }&lt;br /&gt;
    };&lt;br /&gt;
   loop();&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;extended&amp;lt;/tt&amp;gt; is set to true, we retract the jetway. We use the native &amp;lt;tt&amp;gt;interpolate()&amp;lt;/tt&amp;gt; function to interpolate the &amp;lt;tt&amp;gt;position-norm&amp;lt;/tt&amp;gt; property, and then create a loop that modifies the animation properties as the jetway extends/retracts.&lt;br /&gt;
&lt;br /&gt;
  elsif (props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
   {&lt;br /&gt;
   props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).setBoolValue(0);&lt;br /&gt;
   interpolate(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;,&lt;br /&gt;
     0, getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;) * length&lt;br /&gt;
    );&lt;br /&gt;
   gui.popupTip(&amp;quot;Retracting jetway.&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   var loop = func&lt;br /&gt;
    {&lt;br /&gt;
    var position = getprop(&amp;quot;/scenery/airport/jetway[0]/position-norm&amp;quot;);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/x-translation-m&amp;quot;, interpolateTable(xtranslatetable, position) * xtranslate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/y-rotation-deg&amp;quot;, interpolateTable(yrotatetable, position) * yrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-rotation-deg&amp;quot;, interpolateTable(zrotatetable, position) * zrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/z-entrance-rotation-deg&amp;quot;, interpolateTable(zentrancerotatetable, position) * zrotate);&lt;br /&gt;
    setprop(&amp;quot;/scenery/airport/jetway[0]/hood-x-rotation-deg&amp;quot;, interpolateTable(hoodrotatetable, position) * hoodrotate);&lt;br /&gt;
    &lt;br /&gt;
    if (position &amp;gt; 0 and !props.globals.getNode(&amp;quot;/scenery/airport/jetway[0]/extended&amp;quot;).getBoolValue())&lt;br /&gt;
     {&lt;br /&gt;
     settimer(loop, 0);&lt;br /&gt;
     }&lt;br /&gt;
    };&lt;br /&gt;
   loop();&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;extended&amp;lt;/tt&amp;gt; is set to false, we do the exact same thing in reverse.&lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 else&lt;br /&gt;
  {&lt;br /&gt;
  gui.popupTip(&amp;quot;Cannot extend jetway: Your aircraft does not define the required positioning information.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
If our variables ''are'' nil, then we assume that the aircraft lacks animated jetway support and notify the user that this is the case.&lt;br /&gt;
&lt;br /&gt;
= Limitations =&lt;br /&gt;
&lt;br /&gt;
* The jetway does not &amp;quot;know&amp;quot; the position of the aircraft, but rather moves to a predefined location relative to the jetway, unlike in X plane or Microsoft Flight Simulator where the jetways extend to an aircraft (mostly) precisely regardless of its location.&lt;br /&gt;
* Separate gates cannot move independently- you may notice that all jetways extend when you click one of them.&lt;br /&gt;
&lt;br /&gt;
= External links =&lt;br /&gt;
&lt;br /&gt;
* [http://tinypic.com/player.php?v=ajul44&amp;amp;s=4 Video showcasing the animation]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?t=8728 Development thread]&lt;br /&gt;
&lt;br /&gt;
[[Category:Scenery]]&lt;br /&gt;
[[Category:Scenery enhancement]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31067</id>
		<title>FlightGear Newsletter April 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31067"/>
		<updated>2011-04-15T01:27:11Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Doctor Who Fans */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
''We would like to emphasize that the monthly newsletter can not live without the contributions of FlightGear users and developers. Everyone with a wiki account (free to register) can edit the newsletter and every contribution is welcome. So if you know about any FlightGear related projects such as for example updated scenery or aircraft, please do feel invited to add such news to the newsletter.''&lt;br /&gt;
&lt;br /&gt;
== Development news ==&lt;br /&gt;
&lt;br /&gt;
==== Doctor Who Fans ====&lt;br /&gt;
&lt;br /&gt;
Vinura has started work on developing a Doctor Who TARDIS for FlightGear. The exterior model is almost complete in SketchUp.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:TARDIS.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
=== New instruments ===&lt;br /&gt;
The [[Boeing 777-200ER]]'s chronometer has been moved to the generic instruments directory (&amp;lt;tt&amp;gt;Aircraft/Instruments-3d/chronometer&amp;lt;/tt&amp;gt;). This allows aircraft developers to easily implement this clock in their aircraft. All related Nasal code was included in the model xml file, so there's really just one file to be linked to! Some aircraft already make use of this clock, including the [[Boeing 747-400]] and [[Boeing 757-200|757-200]]. &lt;br /&gt;
&lt;br /&gt;
There are several advantages in moving instruments to the generic directoy, some of which are:&lt;br /&gt;
* Easy to be re-used in other aircraft, all you need to do is link to (and position) the model and on some instruments link to a Nasal file.&lt;br /&gt;
* If someone extents the functionality of a generic instrument, it will be automatically extended in all the aircraft that use it.&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
&lt;br /&gt;
Some SriLankan Airlines Liveries have been made by Vinura for the Boeing 767, Airbus A320 and Airbus A340.&lt;br /&gt;
&lt;br /&gt;
For the A320:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-070.png&lt;br /&gt;
Image:Fgfs-screen-072.png&lt;br /&gt;
Image:Fgfs-screen-079.png&lt;br /&gt;
Image:Fgfs-screen-081.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
For the Boeing 767:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-089.png&lt;br /&gt;
Image:Fgfs-screen-088.png&lt;br /&gt;
Image:Fgfs-screen-087.png&lt;br /&gt;
Image:Fgfs-screen-090.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
For the A340:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 1.png&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 2.png&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 3.png&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 4.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The A340 Livery has yet to be uploaded to the FlightGear Livery Database. Also, because the A340 is only slightly flyable, the livery might not be of any use. But the A340 SriLankan Airlines Livery still looks spectacular and is probably the best of all the 3 liveries.&lt;br /&gt;
&lt;br /&gt;
EDIT: The A340-600 Livery can regrettably not be uploaded due to the wrong aircraft type. SriLankan does fly A340's but not the A340-600. I'm sorry for any inconvenience this may have caused.&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
&lt;br /&gt;
=== New scenery ===&lt;br /&gt;
New third-party scenery for the USA's Pacific Northwest (Seattle and Portland, OR) and Rio de Janeiro is now available for download at http://www.stattosoftware.com/flightgear&lt;br /&gt;
&lt;br /&gt;
=== New Buildings ===&lt;br /&gt;
Once again, there are new Eastern Asian buildings !&lt;br /&gt;
&lt;br /&gt;
* Saigon Center - Ho Chi Minh City - Vietnam&lt;br /&gt;
* Mode Gakuen Coccoon Tower - Tokyo - Japan&lt;br /&gt;
* Trade Tower - Seoul - South Korea&lt;br /&gt;
* The Center - Hong Kong - China&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
The generic Concourse C at KDEN was recently replaced with a much better, realistic working model featuring animated jetways. Please enjoy.&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
[[File:Fgfs-screen-085.png|thumb]]&lt;br /&gt;
SriLankan Airlines Livery on an Airbus A320 taken at Dusk.&lt;br /&gt;
&lt;br /&gt;
Spectacular Screenshot...&lt;br /&gt;
&lt;br /&gt;
'''''Your eyes will be amazed!'''''&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
&lt;br /&gt;
Departing from Brisbane International Airport and heading towards Sydney International Airport at a heading of about 203, you will come across some beautiful scenery;&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-020.png&lt;br /&gt;
Image:Fgfs-screen-016.png&lt;br /&gt;
Image:Fgfs-screen-012.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
In the above picture, you can see a road or rails or something. Imagine if a Bus or a train was going along those rails. That would be magnificent! :D&lt;br /&gt;
&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
=== '''''The Good old Cessna Citation X''''' ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Cessna Citation X - Screenshot 1.png]]&lt;br /&gt;
&lt;br /&gt;
I hope to do a monthly review of a specific aircraft. I can't guarantee that I will get to do it every month though because I do have other stuff to attend to.&lt;br /&gt;
&lt;br /&gt;
This is by far one of my favourite little planes! Its reaction time is quite quick. The rudder control is very responsive, even the slightest move of your rudder pedals or the mouse and the rudder on the plane moves. &lt;br /&gt;
&lt;br /&gt;
The acceleration and the animations for the Cessna Citation X is very good. It accelerates quite fast down the runway, building up momentum and then, you lift your joystick up slightly and the nose lifts up just like you want it to. &lt;br /&gt;
&lt;br /&gt;
Regarding the animations, they are extraordinary, they function quite well like for example the flaps or the Wind Brakes or the Landing Gears. The Cockpit is quite well designed and has a lot of instruments just like a real Citation should. &lt;br /&gt;
&lt;br /&gt;
'''''This was the first jet plane that I could actually land properly in.''''' &lt;br /&gt;
&lt;br /&gt;
[[Image:Cessna Citation X - Screenshot 3.png]]&lt;br /&gt;
&lt;br /&gt;
It has a tutorial system built in for people wanting to fly one. It also has several good built-in camera views including views from the passenger seats. &lt;br /&gt;
&lt;br /&gt;
The Cockpit: &lt;br /&gt;
&lt;br /&gt;
(Click on the image for a larger view.)&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Cockpit.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Passengers' Seats:&lt;br /&gt;
&lt;br /&gt;
(Click on the images for a larger view.)&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Passenger View 1.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 2.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Citation X included in the latest FlightGear 2.2 Devlopement Snapshot release is probably the best.&lt;br /&gt;
&lt;br /&gt;
As always, there is always some that goes wrong or fails, for me, that was this;&lt;br /&gt;
&lt;br /&gt;
(Click on the image for a larger view.)&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Citation x error.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If anyone can help me out, send me a message through the FlightGear Wiki. &lt;br /&gt;
&lt;br /&gt;
[http://wiki.flightgear.org/index.php?title=User_talk:Vin&amp;amp;action=edit&amp;amp;section=new Click here to send me a message regarding this error.]&lt;br /&gt;
&lt;br /&gt;
'''Recommendation:'''&lt;br /&gt;
&lt;br /&gt;
I would recommend this plane to people who have already flown planes like the [[Cessna C172P]] or the [[Piper J3 Cub]] and want to progress into Jet aviation. This is a GREAT little starter plane to get you going.&lt;br /&gt;
&lt;br /&gt;
Nevertheless, with all the errors aside, this has to be one of the best planes that I have ever used in FlightGear!&lt;br /&gt;
&lt;br /&gt;
Thanks for reading! :D&lt;br /&gt;
&lt;br /&gt;
'''''Review By: Vinura'''''&lt;br /&gt;
&lt;br /&gt;
[[Image:Cessna Citation X - Screenshot 2.png]]&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
===New articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===New aircraft articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
  categoryRoot=Aircraft&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===Most popular newsletters===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=hot&lt;br /&gt;
  count=5&lt;br /&gt;
  categoryRoot=FlightGear Newsletter&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on youtube ===&lt;br /&gt;
=== New tutorials and screencasts ===&lt;br /&gt;
&lt;br /&gt;
How to use and implement animated jetways!&lt;br /&gt;
&lt;br /&gt;
NOTE: IS IS RECOMMENDED THAT YOU REFER TO SKYOP'S TUTORIAL ON HOW TO USE ANIMATED JETWAYS FIRST. [[Howto: Animated jetways]]&lt;br /&gt;
&lt;br /&gt;
Only use this tutorial of you are completely stuck!&lt;br /&gt;
&lt;br /&gt;
Yes, I know it is long but it is very helpful.&lt;br /&gt;
&lt;br /&gt;
ENJOY!&lt;br /&gt;
&lt;br /&gt;
Part 1:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|uM_rWZorGoQ}}&lt;br /&gt;
&lt;br /&gt;
Part 2:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|0NykU9q_jpc}}&lt;br /&gt;
&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
==== FlyingClub Mayday 1 ====&lt;br /&gt;
The FGFC '''&amp;quot;Mayday 1: Manitoba Rescue&amp;quot;''' operation was held April 2nd, 2011 at CYAV, Winnipeg/St.Andrews, with seven pilots participating. The scenario stated two of Manitoba's major rivers were flooding, and people were stranded along both, so STOL and helicopter pilots were mustered at CYAV, received assignments from ATC, planned their flights, and notified ATC when they were ready to proceed. A total of twenty missions were assigned, sixteen of which were successfully completed in the space of three hours.&lt;br /&gt;
&lt;br /&gt;
The scenario was based around the idea that pilots should have basic skills in addition to merely flying with an autopilot, and was designed to test both their actual flying ability by not having airports at their destinations, and providing no actual navigational data beyond a map or two. They were required to map their routes in territory unknown to them, then fly those routes in their chosen aircraft, land, report in, then return to CYAV to complete a &amp;quot;cycle.&amp;quot; Points were awarded for cycle completion, and points deducted for aircraft crashes. FG Seg faults were not penalized.&lt;br /&gt;
&lt;br /&gt;
Comments back about the operation from pilots have so far been positive. Watch the [http://www.flightgear.org/forums/viewforum.php?f=10&amp;amp;sid=381d9860a9183d143cd2fa8aee16099d Multiplayer Forums] for the next one; there will be one, but at this writing, it has not yet been decided. &lt;br /&gt;
&lt;br /&gt;
* [[FlightGear Flying Club]]&lt;br /&gt;
* [http://flightgearfans.wordpress.com/about/ FGFC WordPress Site ]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=10&amp;amp;t=11551 Mayday 1 Forum Pages]&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common mis-conception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The [[OpenRadar]] project is looking for a new maintainer.&lt;br /&gt;
* The [[FGFSPM]] (FlightGear Package Manager) is looking for a new maintainer.&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
&lt;br /&gt;
...That you can fly '''''backwards''''' in a UFO? While holding the brake button down on your joystick, increase engine throttle and you should start to fly backwards...&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|F7U1bsO7g-E}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2011 04]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31066</id>
		<title>FlightGear Newsletter April 2011</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2011&amp;diff=31066"/>
		<updated>2011-04-15T01:26:27Z</updated>

		<summary type="html">&lt;p&gt;Vin: /* Doctor Who Fans */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
''We would like to emphasize that the monthly newsletter can not live without the contributions of FlightGear users and developers. Everyone with a wiki account (free to register) can edit the newsletter and every contribution is welcome. So if you know about any FlightGear related projects such as for example updated scenery or aircraft, please do feel invited to add such news to the newsletter.''&lt;br /&gt;
&lt;br /&gt;
== Development news ==&lt;br /&gt;
&lt;br /&gt;
==== Doctor Who Fans ====&lt;br /&gt;
&lt;br /&gt;
Vinura has started work on developing a Doctor Who TARDIS for FlightGear. The exterior model is almost complete in SketchUp.&lt;br /&gt;
&lt;br /&gt;
[[File:TARDIS.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
=== New instruments ===&lt;br /&gt;
The [[Boeing 777-200ER]]'s chronometer has been moved to the generic instruments directory (&amp;lt;tt&amp;gt;Aircraft/Instruments-3d/chronometer&amp;lt;/tt&amp;gt;). This allows aircraft developers to easily implement this clock in their aircraft. All related Nasal code was included in the model xml file, so there's really just one file to be linked to! Some aircraft already make use of this clock, including the [[Boeing 747-400]] and [[Boeing 757-200|757-200]]. &lt;br /&gt;
&lt;br /&gt;
There are several advantages in moving instruments to the generic directoy, some of which are:&lt;br /&gt;
* Easy to be re-used in other aircraft, all you need to do is link to (and position) the model and on some instruments link to a Nasal file.&lt;br /&gt;
* If someone extents the functionality of a generic instrument, it will be automatically extended in all the aircraft that use it.&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
&lt;br /&gt;
Some SriLankan Airlines Liveries have been made by Vinura for the Boeing 767, Airbus A320 and Airbus A340.&lt;br /&gt;
&lt;br /&gt;
For the A320:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-070.png&lt;br /&gt;
Image:Fgfs-screen-072.png&lt;br /&gt;
Image:Fgfs-screen-079.png&lt;br /&gt;
Image:Fgfs-screen-081.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
For the Boeing 767:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-089.png&lt;br /&gt;
Image:Fgfs-screen-088.png&lt;br /&gt;
Image:Fgfs-screen-087.png&lt;br /&gt;
Image:Fgfs-screen-090.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
For the A340:&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 1.png&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 2.png&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 3.png&lt;br /&gt;
Image:SriLankan Airlines A340 Screenshot 4.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The A340 Livery has yet to be uploaded to the FlightGear Livery Database. Also, because the A340 is only slightly flyable, the livery might not be of any use. But the A340 SriLankan Airlines Livery still looks spectacular and is probably the best of all the 3 liveries.&lt;br /&gt;
&lt;br /&gt;
EDIT: The A340-600 Livery can regrettably not be uploaded due to the wrong aircraft type. SriLankan does fly A340's but not the A340-600. I'm sorry for any inconvenience this may have caused.&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
&lt;br /&gt;
=== New scenery ===&lt;br /&gt;
New third-party scenery for the USA's Pacific Northwest (Seattle and Portland, OR) and Rio de Janeiro is now available for download at http://www.stattosoftware.com/flightgear&lt;br /&gt;
&lt;br /&gt;
=== New Buildings ===&lt;br /&gt;
Once again, there are new Eastern Asian buildings !&lt;br /&gt;
&lt;br /&gt;
* Saigon Center - Ho Chi Minh City - Vietnam&lt;br /&gt;
* Mode Gakuen Coccoon Tower - Tokyo - Japan&lt;br /&gt;
* Trade Tower - Seoul - South Korea&lt;br /&gt;
* The Center - Hong Kong - China&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
The generic Concourse C at KDEN was recently replaced with a much better, realistic working model featuring animated jetways. Please enjoy.&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
[[File:Fgfs-screen-085.png|thumb]]&lt;br /&gt;
SriLankan Airlines Livery on an Airbus A320 taken at Dusk.&lt;br /&gt;
&lt;br /&gt;
Spectacular Screenshot...&lt;br /&gt;
&lt;br /&gt;
'''''Your eyes will be amazed!'''''&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
&lt;br /&gt;
Departing from Brisbane International Airport and heading towards Sydney International Airport at a heading of about 203, you will come across some beautiful scenery;&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Fgfs-screen-020.png&lt;br /&gt;
Image:Fgfs-screen-016.png&lt;br /&gt;
Image:Fgfs-screen-012.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
In the above picture, you can see a road or rails or something. Imagine if a Bus or a train was going along those rails. That would be magnificent! :D&lt;br /&gt;
&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
=== '''''The Good old Cessna Citation X''''' ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Cessna Citation X - Screenshot 1.png]]&lt;br /&gt;
&lt;br /&gt;
I hope to do a monthly review of a specific aircraft. I can't guarantee that I will get to do it every month though because I do have other stuff to attend to.&lt;br /&gt;
&lt;br /&gt;
This is by far one of my favourite little planes! Its reaction time is quite quick. The rudder control is very responsive, even the slightest move of your rudder pedals or the mouse and the rudder on the plane moves. &lt;br /&gt;
&lt;br /&gt;
The acceleration and the animations for the Cessna Citation X is very good. It accelerates quite fast down the runway, building up momentum and then, you lift your joystick up slightly and the nose lifts up just like you want it to. &lt;br /&gt;
&lt;br /&gt;
Regarding the animations, they are extraordinary, they function quite well like for example the flaps or the Wind Brakes or the Landing Gears. The Cockpit is quite well designed and has a lot of instruments just like a real Citation should. &lt;br /&gt;
&lt;br /&gt;
'''''This was the first jet plane that I could actually land properly in.''''' &lt;br /&gt;
&lt;br /&gt;
[[Image:Cessna Citation X - Screenshot 3.png]]&lt;br /&gt;
&lt;br /&gt;
It has a tutorial system built in for people wanting to fly one. It also has several good built-in camera views including views from the passenger seats. &lt;br /&gt;
&lt;br /&gt;
The Cockpit: &lt;br /&gt;
&lt;br /&gt;
(Click on the image for a larger view.)&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Cockpit.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Passengers' Seats:&lt;br /&gt;
&lt;br /&gt;
(Click on the images for a larger view.)&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Cessna Citation X Passenger View 1.png&lt;br /&gt;
Image:Cessna Citation X Passenger View 2.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Citation X included in the latest FlightGear 2.2 Devlopement Snapshot release is probably the best.&lt;br /&gt;
&lt;br /&gt;
As always, there is always some that goes wrong or fails, for me, that was this;&lt;br /&gt;
&lt;br /&gt;
(Click on the image for a larger view.)&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Citation x error.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If anyone can help me out, send me a message through the FlightGear Wiki. &lt;br /&gt;
&lt;br /&gt;
[http://wiki.flightgear.org/index.php?title=User_talk:Vin&amp;amp;action=edit&amp;amp;section=new Click here to send me a message regarding this error.]&lt;br /&gt;
&lt;br /&gt;
'''Recommendation:'''&lt;br /&gt;
&lt;br /&gt;
I would recommend this plane to people who have already flown planes like the [[Cessna C172P]] or the [[Piper J3 Cub]] and want to progress into Jet aviation. This is a GREAT little starter plane to get you going.&lt;br /&gt;
&lt;br /&gt;
Nevertheless, with all the errors aside, this has to be one of the best planes that I have ever used in FlightGear!&lt;br /&gt;
&lt;br /&gt;
Thanks for reading! :D&lt;br /&gt;
&lt;br /&gt;
'''''Review By: Vinura'''''&lt;br /&gt;
&lt;br /&gt;
[[Image:Cessna Citation X - Screenshot 2.png]]&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
===New articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===New aircraft articles===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=new&lt;br /&gt;
  count=10&lt;br /&gt;
  categoryRoot=Aircraft&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
===Most popular newsletters===&lt;br /&gt;
&amp;lt;DynamicArticleList&amp;gt;&lt;br /&gt;
  type=hot&lt;br /&gt;
  count=5&lt;br /&gt;
  categoryRoot=FlightGear Newsletter&lt;br /&gt;
&amp;lt;/DynamicArticleList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on youtube ===&lt;br /&gt;
=== New tutorials and screencasts ===&lt;br /&gt;
&lt;br /&gt;
How to use and implement animated jetways!&lt;br /&gt;
&lt;br /&gt;
NOTE: IS IS RECOMMENDED THAT YOU REFER TO SKYOP'S TUTORIAL ON HOW TO USE ANIMATED JETWAYS FIRST. [[Howto: Animated jetways]]&lt;br /&gt;
&lt;br /&gt;
Only use this tutorial of you are completely stuck!&lt;br /&gt;
&lt;br /&gt;
Yes, I know it is long but it is very helpful.&lt;br /&gt;
&lt;br /&gt;
ENJOY!&lt;br /&gt;
&lt;br /&gt;
Part 1:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|uM_rWZorGoQ}}&lt;br /&gt;
&lt;br /&gt;
Part 2:&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|0NykU9q_jpc}}&lt;br /&gt;
&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
==== FlyingClub Mayday 1 ====&lt;br /&gt;
The FGFC '''&amp;quot;Mayday 1: Manitoba Rescue&amp;quot;''' operation was held April 2nd, 2011 at CYAV, Winnipeg/St.Andrews, with seven pilots participating. The scenario stated two of Manitoba's major rivers were flooding, and people were stranded along both, so STOL and helicopter pilots were mustered at CYAV, received assignments from ATC, planned their flights, and notified ATC when they were ready to proceed. A total of twenty missions were assigned, sixteen of which were successfully completed in the space of three hours.&lt;br /&gt;
&lt;br /&gt;
The scenario was based around the idea that pilots should have basic skills in addition to merely flying with an autopilot, and was designed to test both their actual flying ability by not having airports at their destinations, and providing no actual navigational data beyond a map or two. They were required to map their routes in territory unknown to them, then fly those routes in their chosen aircraft, land, report in, then return to CYAV to complete a &amp;quot;cycle.&amp;quot; Points were awarded for cycle completion, and points deducted for aircraft crashes. FG Seg faults were not penalized.&lt;br /&gt;
&lt;br /&gt;
Comments back about the operation from pilots have so far been positive. Watch the [http://www.flightgear.org/forums/viewforum.php?f=10&amp;amp;sid=381d9860a9183d143cd2fa8aee16099d Multiplayer Forums] for the next one; there will be one, but at this writing, it has not yet been decided. &lt;br /&gt;
&lt;br /&gt;
* [[FlightGear Flying Club]]&lt;br /&gt;
* [http://flightgearfans.wordpress.com/about/ FGFC WordPress Site ]&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=10&amp;amp;t=11551 Mayday 1 Forum Pages]&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common mis-conception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The [[OpenRadar]] project is looking for a new maintainer.&lt;br /&gt;
* The [[FGFSPM]] (FlightGear Package Manager) is looking for a new maintainer.&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
&lt;br /&gt;
...That you can fly '''''backwards''''' in a UFO? While holding the brake button down on your joystick, increase engine throttle and you should start to fly backwards...&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|F7U1bsO7g-E}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2011 04]]&lt;/div&gt;</summary>
		<author><name>Vin</name></author>
	</entry>
</feed>