Boolean enumeration: Difference between revisions

From m204wiki
Jump to navigation Jump to search
Line 41: Line 41:
<p class="code">if %bool and (%y gt %x) Then
<p class="code">if %bool and (%y gt %x) Then
</p>
</p>
==Automatic conversion of numbers to boolean==
==Automatic conversion of numbers to Boolean==
In <var class="product">Sirius Mods 8.1</var> and later, it is also possible to assign a number to a boolean variable. When this is done, the number 0 is converted to <var>False</var> and every other value is converted to <var>True</var>. This is especially useful for assigning the result of a comparison to a boolean:
In <var class="product">Sirius Mods 8.1</var> and later, it is also possible to assign a number to a <var>Boolean</var> variable. When this is done, the number 0 is converted to <var>False</var> and every other value is converted to <var>True</var>. This is especially useful for assigning the result of a comparison to a boolean:
<p class="code">%bool = %x gt %y
<p class="code">%bool = %x gt %y
</p>
</p>
This assignment can, of course, be implicit when a method has a boolean parameter:
This assignment can, of course, be implicit when a method has a <var>Boolean</var> parameter:
<p class="code">local subroutine foo(%ok is boolean)
<p class="code">local subroutine foo(%ok is boolean)
...
...
Line 53: Line 53:
<p class="code">if $setg(''NAME', %name) then
<p class="code">if $setg(''NAME', %name) then
</p>
</p>
one can also assign the result of a method or $function to a boolean:
one can also assign the result of a method or $function to a <var>Boolean</var>:
<p class="code">%setgSuccess is boolean
<p class="code">%setgSuccess is boolean
...
...
%setgSuccess = $setg(''NAME', %name)
%setgSuccess = $setg(''NAME', %name)
</p>
</p>
One note of caution. Numbers are [[Intrinsic classes|intrinsic variables]] and, as such string values are automatically converted to numbers. Any string that can't be converted to a number is treated as 0. So, if <var>%n</var> is declared as <var>Float</var>, the following:
One note of caution. Numbers are [[Intrinsic classes|intrinsic variables]] and, as such, string values are automatically converted to numbers. Any string that can't be converted to a number is treated as 0. So, if <code>%n</code> is declared as <var>Float</var>, the following:
<p class="code">%n = '1234.56'
<p class="code">%n = '1234.56'
</p>
</p>
would result in <var>%n</var> containing the number <var>1234.56</var>. The following:
would result in <code>%n</code> containing the number <code>1234.56</code>. The following:
<p class="code">%n = 'Not a number'
<p class="code">%n = 'Not a number'
</p>
</p>
would result in <var>%n</var> containing the number <var>0</var>. The following:
would result in <code>%n</code> containing the number <code>0</code>. The following:
<p class="code">%n = 'ten'
<p class="code">%n = 'ten'
</p>
</p>
would also result in <var>%n</var> containing the number <var>0</var>. Hopefully, this is not too surprising. In addition, it should not be surprising that the following:
would also result in <code>%n</code> containing the number <code>0</code>. Hopefully, this is not too surprising. In addition, it should not be surprising that the following:
<p class="code">%n = 'true'
<p class="code">%n = 'true'
</p>
</p>
would also result in <var>%n</var> containing the number <var>0</var>. However, if <var>%bool</var> is a boolean,
would also result in <code>%n</code> containing the number <code>0</code>. However, if <code>%bool</code> is a <var>boolean</var>,
<p class="code">%bool = 'true'
<p class="code">%bool = 'true'
</p>
</p>
would result in <var>%bool</var> containing <var>False</var> because when booleans are set from intrinsic variables, the intrinsic values are treated as numbers so 'true' was converted to the number <var>0</var> before being assigned to <var>%bool</var>.
would result in <code>%bool</code> containing <code>False</code> because when <var>boolean</var>s are set from intrinsic variables, the intrinsic values are treated as numbers so 'true' was converted to the number <code>0</code> before being assigned to <code>%bool</code>.


Of course, there really be no good reason to assign a string (or numeric) literal to a boolean. If one wanted to set a boolean variable to a literal value, one should simply specify the unquoted literal value as one does when setting any enumeration value:
Of course, there really be no good reason to assign a string (or numeric) literal to a boolean. If one wanted to set a boolean variable to a literal value, one should simply specify the unquoted literal value as one does when setting any enumeration value:
Line 80: Line 80:
%bool = false
%bool = false
</p>
</p>
In the case where one has a string that contains either "True" or "False", on can use the standard enumeration <var>FromString</var> method to set the boolean variable:
In the case where one has a string that contains either "True" or "False", on can use the standard enumeration <var>FromString</var> method to set the <var>Boolean</var> variable:
<p class="code">%bool = %(boolean):fromString(%string)
<p class="code">%bool = %(boolean):fromString(%string)
</p>
</p>
If <var>%string</var> does not contain "True" or "False" (case independent) then an <var>InvalidValue</var> exception is thrown by <var>FromString</var>.
If <code>%string</code> does not contain "True" or "False" (case independent) then an <var>InvalidValue</var> exception is thrown by <var>FromString</var>.
 
===Limitations===
===Limitations===
Even in <var class="product">Sirius Mods 8.1</var> and later there are a few places where numbers are not automatically converted to booleans:
Even in <var class="product">Sirius Mods 8.1</var> and later there are a few places where numbers are not automatically converted to booleans:
<ul>
<ul>
<li>As inputs to boolean parameters to complex subroutines. Since complex subroutine can be called before they are declared, doing such automatic conversion would be very complex so is currently not supported. If the automatic conversion of numeric inputs to boolean parameters is required for a complex subroutine, one option might be to try to convert the complex subroutine to a [[Local and Common entities|Common subroutine]].
<li>As inputs to <var>Boolean</var> parameters to complex subroutines. Since complex subroutine can be called before they are declared, doing such automatic conversion would be very complex so is currently not supported. If the automatic conversion of numeric inputs to <var>Boolean</var> parameters is required for a complex subroutine, one option might be to try to convert the complex subroutine to a [[Local and Common entities|Common subroutine]].
<li>As method objects to enhancement methods for the boolean class. For example, if one had
 
<li>As method objects to enhancement methods for the <var>Boolean</var> class. For example, if one had
<p class="code">local function (boolean):xor(%what is boolean) is boolean
<p class="code">local function (boolean):xor(%what is boolean) is boolean
</p>
</p>
Line 94: Line 96:
<p class="code">%bool = (%x gt %y):xor(%y gt %z)
<p class="code">%bool = (%x gt %y):xor(%y gt %z)
</p>
</p>
Fortunately, boolean enhancement methods are few and far between so this restriction is not likely to be a major problem.
Fortunately, <var>Boolean</var> enhancement methods are few and far between, so this restriction is not likely to be a major problem.
</ul>
</ul>
Finally, while in <var class="product">Sirius Mods 8.1</var> and later, numeric values are automatically converted to boolean when assigned to boolean variable, the inverse is not true. That is, boolean values are not automatically converted to numeric values when assigned to intrinsic variables. The main implication of this is that if one is migrating from using <var>Float</var> parameters as boolean switches, the migration should start by converting the parameter declaration to <var>Boolean</var>. This might require changing some of the code inside the method but it is also likely that no code changes would be required. Once this is done, code that invokes the method can be modified to pass boolean rather than float values.
Finally, while in <var class="product">Sirius Mods 8.1</var> and later, numeric values are automatically converted to boolean when assigned to a <var>Boolean</var> variable, the inverse is not true. That is, to have <var>Float</var> parameters as boolean switches, the migration should start by converting the parameter declaration to <var>Boolean</var>. This might require changing some of the code inside the method, but it is also likely that no code changes would be required. Once this is done, code that invokes the method can be modified to pass <var>Boolean</var> rather than <var>Float</var> values.


==Using booleans==  
==Using booleans==  

Revision as of 14:12, 11 October 2012

The Boolean enumeration implements the standard logical paradigm of "true" and "false".

While, in some sense, it is just like any other enumeration, because the concept of true and false is so basic to programming, Boolean variables are treated specially by User Language.

Boolean enumeration values

The system Boolean enumeration values are:

  • True
  • False

However, like all other enumerations, a Boolean variable can also be unset so have a null value. While this can be useful in detecting references to unset variables, it can also be problematic in certain sitiuations. Use of the Initial clause on variable declarations and the Default clause on method parameter declarations can mitigate most of these issues, nevertheless it is important to keep in mind the possibility of a Boolean variable being null.

Declaring boolean variables

Boolean variables can be declared the same way any enumeration variables are declared, with the keyword Enumeration followed by the class name:

%truth is enumeration boolean

However, because boolean processing is such a basic part of any programming language, Boolean variables can be declared without the Enumeration keyword:

%truth is boolean

This is also true for method variables and results. For example, then following:

function foo(%n is float, %test is enumeration boolean) - is enumeration boolean

is identical to

function foo(%n is float, %test is boolean) is boolean

Using booleans in If conditions

The whole point of Boolean variables is to be able to test them for truth and, depending on the result, perform some processing. For example, if %bool is a Boolean variable, the following performs the contents of the If block if %bool is set to True:

if %bool then

Note that in this example, if %bool is not set (null), then the request would be canceled with a null object reference error.

Using logical operators with booleans

User language has three logical operators:

  • Not
  • And
  • Or

Strictly speaking, in User Language these operators actually operate on numeric values where 0 is treated as False and any non-zero value is treated as True. However, because of the importance of boolean logic in programming, Boolean variables or values can be used instead of numbers for these operators. A boolean True is treated as 1 and a False value is treated as 0. As such, boolean variables can be used in logical operations as in:

if not %bool then

or

if %bool and (%y gt %x) Then

Automatic conversion of numbers to Boolean

In Sirius Mods 8.1 and later, it is also possible to assign a number to a Boolean variable. When this is done, the number 0 is converted to False and every other value is converted to True. This is especially useful for assigning the result of a comparison to a boolean:

%bool = %x gt %y

This assignment can, of course, be implicit when a method has a Boolean parameter:

local subroutine foo(%ok is boolean) ... %(local):foo(%x gt %y)

Of course, some methods or $functions return a 0 indicating success and a non-zero value indicating an error. So, just as one can do:

if $setg(NAME', %name) then

one can also assign the result of a method or $function to a Boolean:

%setgSuccess is boolean ... %setgSuccess = $setg(NAME', %name)

One note of caution. Numbers are intrinsic variables and, as such, string values are automatically converted to numbers. Any string that can't be converted to a number is treated as 0. So, if %n is declared as Float, the following:

%n = '1234.56'

would result in %n containing the number 1234.56. The following:

%n = 'Not a number'

would result in %n containing the number 0. The following:

%n = 'ten'

would also result in %n containing the number 0. Hopefully, this is not too surprising. In addition, it should not be surprising that the following:

%n = 'true'

would also result in %n containing the number 0. However, if %bool is a boolean,

%bool = 'true'

would result in %bool containing False because when booleans are set from intrinsic variables, the intrinsic values are treated as numbers so 'true' was converted to the number 0 before being assigned to %bool.

Of course, there really be no good reason to assign a string (or numeric) literal to a boolean. If one wanted to set a boolean variable to a literal value, one should simply specify the unquoted literal value as one does when setting any enumeration value:

%bool = true ... %bool = false

In the case where one has a string that contains either "True" or "False", on can use the standard enumeration FromString method to set the Boolean variable:

%bool = %(boolean):fromString(%string)

If %string does not contain "True" or "False" (case independent) then an InvalidValue exception is thrown by FromString.

Limitations

Even in Sirius Mods 8.1 and later there are a few places where numbers are not automatically converted to booleans:

  • As inputs to Boolean parameters to complex subroutines. Since complex subroutine can be called before they are declared, doing such automatic conversion would be very complex so is currently not supported. If the automatic conversion of numeric inputs to Boolean parameters is required for a complex subroutine, one option might be to try to convert the complex subroutine to a Common subroutine.
  • As method objects to enhancement methods for the Boolean class. For example, if one had

    local function (boolean):xor(%what is boolean) is boolean

    the following would not result in a compilation error:

    %bool = (%x gt %y):xor(%y gt %z)

    Fortunately, Boolean enhancement methods are few and far between, so this restriction is not likely to be a major problem.

Finally, while in Sirius Mods 8.1 and later, numeric values are automatically converted to boolean when assigned to a Boolean variable, the inverse is not true. That is, to have Float parameters as boolean switches, the migration should start by converting the parameter declaration to Boolean. This might require changing some of the code inside the method, but it is also likely that no code changes would be required. Once this is done, code that invokes the method can be modified to pass Boolean rather than Float values.

Using booleans

Many methods, for example the XmlDoc API Exists function, return a Boolean enumeration.

Unlike other Janus SOAP ULI enumerations, Boolean enumeration values are usable as the condition in an If statement:

%recset is object recordSet in file sirfiled ... find records to %recset rectype = 'FILE' end find ... if %recset:isEmpty then print 'No records found!' end if

In the above example, the IsEmpty method returns a Boolean enumeration value. Strictly speaking, the If clause expects a numeric zero or non-zero value as its operand, but in this context Janus SOAP ULI automatically converts a True to a 1 and a False to a 0.

Other places where a Boolean value can be used, that is, where it is automatically converted to the 0 or 1 that User Language expects are:

  • As a Repeat statement operand.
  • As an operand for a logical operator such as Not, And, or Or. This would usually be in an If or Repeat statement.

You can also use Boolean literals in these contexts, but they must be completely qualified as Booleans: otherwise there is a syntactic ambiguity between the values True or False and fields by the name of True or False. The following is syntactically valid:

if %(boolean):true then print 'Truth be told' end if

Enumeration methods

Besides the common enumeration methods, the system Boolean enumeration has additional methods available, which are described here.

IsFalse function

This function examines a Boolean enumeration and returns an integer (0 or 1) according to the Boolean value (True or False).

IsFalse syntax

%num = bool:IsFalse

Syntax terms

%num If specified, a number variable that is assigned the value 0 if the value of bool isTrue, and 1 if bool is False.
bool A Boolean enumeration variable or an expression that results in a Boolean enumeration.

IsTrue function

This function examines a Boolean enumeration and returns an integer (1 or 0) according to the Boolean value (True or False).

IsTrue syntax

%num = bool:IsTrue

Syntax terms

%num If specified, a number variable that is assigned the value 1 if the value of bool isTrue, and 0 if bool is False.
bool A Boolean enumeration variable or an expression that results in a Boolean enumeration.