Howto:Use vectors and foreach loops to write shorter code: Difference between revisions
Red Leader (talk | contribs) (Use Nasal syntax-highlighting) |
Philosopher (talk | contribs) m (use separate arguments to setprop() instead of concatenation) |
||
Line 23: | Line 23: | ||
var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"]; | var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"]; | ||
foreach(var line; lines) { | foreach(var line; lines) { | ||
setprop("/controls/cdu | setprop("/controls/cdu", cdu, line, "click"); | ||
} | } | ||
Line 34: | Line 34: | ||
var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"]; | var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"]; | ||
foreach(var line; lines) { | foreach(var line; lines) { | ||
setprop("/controls/cdu | setprop("/controls/cdu", cdu, line, "click"); | ||
} | } | ||
} | } | ||
Line 58: | Line 58: | ||
var init_cdu_types= func(what) { | var init_cdu_types= func(what) { | ||
foreach(var w; what) { | foreach(var w; what) { | ||
setprop("/controls/cdu | setprop("/controls/cdu", cdu, w, "click"); | ||
} | } | ||
} | } | ||
Line 98: | Line 98: | ||
var init_cdu_types= func(what,value="click") { | var init_cdu_types= func(what,value="click") { | ||
foreach(var w; what) { | foreach(var w; what) { | ||
setprop("/controls/cdu | setprop("/controls/cdu", cdu, w, value); | ||
} | } | ||
} | } | ||
Line 123: | Line 123: | ||
var create_with_suffix = func(prefix,start,end,suffix) { | var create_with_suffix = func(prefix,start,end,suffix) { | ||
var result = []; | var result = []; | ||
for (var i=start;i= | for (var i=start;i<=end;i+=1) { | ||
var s= prefix ~ i ~ suffix; | var s= prefix ~ i ~ suffix; | ||
append(result,s); | append(result,s); |
Revision as of 15:19, 7 January 2015
The FlightGear forum has a subforum related to: Nasal Scripting |
Nasal scripting |
---|
Nasal internals |
---|
Memory Management (GC) |
- Last updated: 02/2012
- Contributors: Omega95, Hooray
Objective: Demonstrate how the use of Nasal vectors and foreach loops may help to create shorter and less redundant Nasal code.
Consider the following snippet of code, taken from Howto: Implement a Flight Management Computer in Nasal.
setprop("/controls/cdu[" ~ cdu ~ "]/l1-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/l2-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/l3-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/l4-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/l5-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/l6-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/l7-type", "click");
As you can see, this is a fairly repetitive piece of code, which could be easily generalized, so that only a single setprop() call is used in a loop (foreach). It could be rewritten like this:
var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"];
foreach(var line; lines) {
setprop("/controls/cdu", cdu, line, "click");
}
Then, you could also use a small helper function (method):
var init_lines= func {
var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"];
foreach(var line; lines) {
setprop("/controls/cdu", cdu, line, "click");
}
}
The nice thing is, that we get less code, which is more general - i.e. it will be much easier to change things later on, so that support for more CDU/FMC lines could be added easily for example.
Now, when looking through the code in Howto: Implement a Flight Management Computer in Nasal, we can find more code, which looks fairly similar:
setprop("/controls/cdu[" ~ cdu ~ "]/r1-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/r2-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/r3-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/r4-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/r5-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/r6-type", "click");
setprop("/controls/cdu[" ~ cdu ~ "]/r7-type", "click");
The only thing different here is that we have "r1..r7-type" rather than "l1..l7". So, we could just take our previous function and generalize it some more:
var init_cdu_types= func(what) {
foreach(var w; what) {
setprop("/controls/cdu", cdu, w, "click");
}
}
This could now be easily called during initialization to set up the properties like this:
var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"];
init_cdu_types(lines);
var lines = ["r1-type", "r2-type", "r3-type", "r4-type", "r5-type", "r6-type", "r7-type"];
init_cdu_types(lines);
Now, looking further through the code, there are more opportunities to generalize our little helper function:
## Field Values
setprop("/controls/cdu[" ~ cdu ~ "]/display/l1-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/l2-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/l3-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/l4-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/l5-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/l6-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/l7-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r1-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r2-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r3-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r4-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r5-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r6-label", "");
setprop("/controls/cdu[" ~ cdu ~ "]/display/r7-label", "");
The only thing that's different here, is the final setprop argument - which is empty in this case, so we could just change our function to support an additional argument:
var init_cdu_types= func(what,value="click") {
foreach(var w; what) {
setprop("/controls/cdu", cdu, w, value);
}
}
Note, that we have provided a default value here (which is "click"), so that the previous function calls don't need to be changed.
With the changes in place, our init code could be made even shorter:
var lines = ["l1-type", "l2-type", "l3-type", "l4-type", "l5-type", "l6-type", "l7-type"];
init_cdu_types(lines);
var lines = ["r1-type", "r2-type", "r3-type", "r4-type", "r5-type", "r6-type", "r7-type"];
init_cdu_types(lines);
var lines = ["/display/l1-label", "/display/l2-label", "/display/l3-label", "/display/l4-label", "/display/l5-label","/display/l6-label", "/display/l7-label","/display/r1-label", "/display/r2-label", "/display/r3-label", "/display/r4-label", "/display/r5-label","/display/r6-label", "/display/r7-label"];
init_cdu_types(lines,"");
Obviously, there are some more opportunities - such as automatically creating these vectors, too. Which is also trivial to do:
var create_with_suffix = func(prefix,start,end,suffix) {
var result = [];
for (var i=start;i<=end;i+=1) {
var s= prefix ~ i ~ suffix;
append(result,s);
}
return result;
}
So, now we have a helper function, which automatically creates these vectors. Which can be used like this:
var left = create_with_suffix('l',1,7,'-type');
var right = create_with_suffix('r',1,7,'-type');
var display_right = create_with_suffix('display/l',1,7,'-label');
var display_left = create_with_suffix('display/r',1,7,'-label');
init_cdu_types(left);
init_cdu_types(right);
init_cdu_types(display_right);
init_cdu_types(display_left);