Featured

JAWS Scripting Tip: Optional Parameters

JAWS is a screen reader developed by Freedom Scientific. It includes a scripting language that allows users to customize the behavior of JAWS.

Many programming languages such as C++, C#, and Modern JavaScript support the concept of optional function parameters for which you supply a default value for the parameter. In C++ this might be done as follows.

std::wstring GetFavoriteNumberMessage(int64_t number = 42)
{
    std::wstringstream message;
    message
        << L"Hello. My favorite number is "
        << number
        << L". What is your favorite number?\n";
    return message.str();
}

See source on godbolt.org.

The JAWS scripting language supports optional parameters using the optional keyword, as follows.


string function GetFavoriteNumberMessage(optional int number)
  var string message = FormatString(
    "Hello. My favorite number is %1. What is your favorite number?",
     number)
  return message
endFunction

However, there is no direct method of assigning a default value for the optional parameter. If you were to call the function is as without specifying a value for the number parameter the number will be inserted into the returned message as an empty string. This is most likely not the desired behavior.

When the caller does not specify the value of an optional parameter, it does not resolve to 0 or false within the function; this is a common misconception. Instead the unspecified parameter resolves to nullptr. The misconception that the unspecified parameter resolves to 0 or false is a result of the fact that when nullptr is typecast to an int the result is 0 or false. However, if the unspecified parameter is typecast to a string the result is an empty string. This is why in the above example the number will be inserted into the returned message as an empty string; the number parameter is typecast to a string by the FormatString function. If the unspecified parameter did resolve to 0 or false within the function it would be inserted to the returned message as 0!

This problem can be resolved as follows.

string function GetFavoriteNumberMessage(optional int number)
    if (!DidCallerSpecifyTheValueOfTheParameter(number))
      number = 42
    endIf
    var string message = FormatString(
      "Hello. My favorite number is %1. What is your favorite number?",
      number)
    return message
endFunction

Unfortunately, there is no DidCallerSpecifyTheValueOfTheParameter function in the JAWS scripting language, so do not bother looking it up. However, there is a function that can achieve the same goal.

Behind the scenes all variables in the JAWS scripting language are VARIANTs (yes we are aware that there are modern alternatives that are vastly superior but the JAWS scripting language is very old; it has its roots in the JAWS macro language that was included in JAWS for DOS). One benefit of a VARIANT is it supports the concept of a VARTYPE or variant type. Furthermore, there is a VT_EMPTY variant type. Finally, there is a rarely used GetVariantType built-in script function that “determines the type of a variable”.

Thus, it is possible to assign a default value for an optional parameter as follows.

string function GetFavoriteNumberMessage(optional int number)
    if (GetVariantType(number) == VT_EMPTY)
      number = 42
    endIf
    var string message = FormatString(
      "Hello. My favorite number is %1. What is your favorite number?",
      number)
    return message
endFunction

Note that some people may think this is unnecessary because it is enough to rely on the perceived unspecified parameter resolves to 0 or false behavior. This is wrong for two reasons.

  • As I have already pointed this perceived behavior is not what is actually happening. The unspecified parameter actually resolves to nullptr.
  • In many cases, even if the perceived unspecified parameter resolves to 0 or false behavior may not be what is desired.

Every other programming language that supports the concept of optional parameters; such as C++, C#, and Modern JavaScript ; allows the value of the optional parameters to be explicitly defined. The purpose of the following code block is to add the same capabilities to optional parameters in the JAWS Scripting Language.

if (GetVariantType(number) == VT_EMPTY)
  number = 42
endIf

This is the only way to assign a non nullptr value for an optional parameter in the JAWS Scripting Language. You should consider doing this even for parameters where the default value is 0 or nullptr because explicitly specifying the value of your default parameters rather that making people who read your code guess what the behavior will be is just being polite.

Note that using this technique is absolutely necessary when overriding a built-in script function such as the SayObjectTypeAndText function in your scripts. The default value of the includeContainerName is true, not false. Failure to do this when overriding the SayObjectTypeAndText function will change the behavior of your function from the default resulting in hard to find bugs.

Advertisement