Hi fellow wiki editors!

To help newly registered users get more familiar with the wiki (and maybe older users too) there is now a {{Welcome to the wiki}} template. Have a look at it and feel free to add it to new users discussion pages (and perhaps your own).

I have tried to keep the template short, but meaningful. /Johan G

Howto:Use helper functions to simplify complex conditionals in Nasal

From FlightGear wiki
Jump to: navigation, search
This article is a stub. You can help the wiki by expanding it.
  • Last updated: 12/1/2016
  • Contributors: Omega95, Hooray

Objective: Demonstrate how to use Nasal helper functions to turn complex conditional expressions into short, and human-readable checks:

Whenever you have complex conditionals, that end up being fairly long, it's a good idea to use little helper functions. For example, consider the following snippet of code, taken from Howto: Implement a Flight Management Computer in Nasal.

if ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 1) ~ "]/id") != nil) {
    # ...
} else {
    # ...
}

if ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 2) ~ "]/id") != nil) {
    # ...
} else {
    # ...
}

The only thing that's different here is the waypoint index, so the whole expression could be moved into a function like this:

var fplan_has_wp = func(flightplan, number){
    return ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + number) ~ "]/id") != nil);
}

This function will return a boolean, indicating if the waypoint is available or not.

Your conditionals would become much shorter and much more readable then, too:

if (fplan_has_wp(flightplan, 1)) {
    # ...
} else {
    # ...
}

if (fplan_has_wp(flightplan, 2)) {
    # ...
} else {
    # ...
}

if (fplan_has_wp(flightplan, 3)) {
    # ...
} else {
    # ...
}

So, we can simplify this conditional block:

## Display WP IDs and ALTs
   
if ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") ~ "]/id") != nil) and (getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first")) ~ "]/id") != "")) {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l1", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first")) ~ "]/id"));
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r1", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first")) ~ "]/alt"));
} else {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l1", "-");
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r1", "-");
}
 
if ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 1) ~ "]/id") != nil) and (getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 1) ~ "]/id") != "")) {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l2", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 1) ~ "]/id"));
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r2", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 1) ~ "]/alt"));
} else {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l2", "-");
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r2", "-");
}
 
if ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 2) ~ "]/id") != nil) and (getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 2) ~ "]/id") != "")) {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l3", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 2) ~ "]/id"));
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r3", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 2) ~ "]/alt"));
} else {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l3", "-");
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r3", "-");
}
 
if ((getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 3) ~ "]/id") != nil) and (getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 3) ~ "]/id") != "")) {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l4", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 3) ~ "]/id"));
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r4", getprop(fmcFPtree ~ "flightplan[" ~ plan ~ "]/wp[" ~ (getprop(fmcFPtree ~ "FPpage[" ~ plan ~ "]/first") + 3) ~ "]/alt"));
} else {
    setprop("/controls/cdu[" ~ cdu ~ "]/display/l4", "-");
    setprop("/controls/cdu[" ~ cdu ~ "]/display/r4", "-");
}