I had a layout object that wasn't behaving to hide the object. If you clicked a checkbox, a variable list element was set to True. I was assuming that, like the rest of the universe, Filemaker only had 2 boolean values, so my test said to hide if the value = 0. False, 0, and blank should all cause the object to hide. However the object was still visible with the box unchecked. It turns out that "not defined" is different than "blank" and is not considered true or false. Is this a bug?
I‘d do the test the opposite way:
hide if not value
as 0 can‘t be = empty
Yes, the solution was simple once I figured out what was happening. But there are places Filemaker interprets "blank" as false, and I thought the basic definition of Boolean was only 2 logical states...
They provide the GetAsBoolean function for exactly that purpose.
The problem is your query: value = 0
If you make it value = False it works for 0 and empty
@Otmar, I think we should move your reply straight into the "Gotchas" channel.
I have to admit that I am perplexed by the above statements.
The way that I read it, it seems as though the implication of the above is that the following should return a value of 1 (or True), and yet, such has never been my experience:
"" = False
Rather, my experience is that False is simply a reserved word that evaluates to 0.
0 = False // returns 1 Exact( 0 ; False ) // returns 1 "" = False // returns 0
Could very well be that I am simply misinterpreting what @Otmar posted. Not super important for me to know, but figured I'd mention that I find it perplexing, just in case anyone else is in the same boat.
Results from the Data Viewer:
Let ( value = "" ; value = False ) // 0 Let ( value = "" ; value = True ) // 0 Let ( value = "" ; value ≠ True ) // 1 Let ( value = "" ; value ≠ False ) // 1 Let ( value = "" ; GetAsBoolean ( value ) = False ) // 1 Let ( value = "" ; GetAsBoolean ( value ) = True ) // 0 Let ( value = "" ; GetAsBoolean ( value ) ≠ False ) // 0 Let ( value = "" ; GetAsBoolean ( value ) ≠ True ) // 1 Let ( value = table::numberField ; value = False ) // 1, when the field is empty Let ( value = table::textField ; value = False ) // 0, when the field is empty Let ( value = GetAsNumber(table::textField) ; value = False ) // 0, when the field is empty Let ( value = table::textField ; GetAsNumber(value) = False ) // 0, when the field is empty
Looks like a "real" field is handled different than a local calculation var:
BooleanTest.fmp12.zip (84.2 KB)
Maybe because Let ( value = "" ; .... clears the var? so it's not an empty var but a not existing?
@Otmar Many thanks -- that file really helped me out.
It looks as though behavior is different depending on the data type of the field,
i.e. for number fields:
Table::EmptyNumberField = False // returns 1
for text fields:
Table::EmptyTextField = False // returns 0
For as long as I have ever thought about these things, I have only been aware of the behavior exhibited by Text fields/results, and had incorrectly assumed that I could generalize that behavior to Number fields/results.
BooleanTest_Updated.fmp12.zip (85.7 KB)
It actually makes sense to me, once I see what I believe is the full picture. When one of the comparison arguments is a string, then both are treated as a string for the comparison. Just like what we would see with a > or < comparison -- but, just like the first time I had to puzzle through the behavior with > and <, it caught be by surprise.
It seems as though the engine assumptions about data types can't be shaken. When I apply GetAsNumber( ) to empty strings, the stringiness isn't affected, they don't get treated as false.
The message I get from this is that GetAsBoolean( ) continues to be the best way to ensure that we have a boolean regardless of the input.
Absolutely agreed. I find it enjoyable to tease out the nuances of how and when the implicit type coercion happens, but even if I thought I had expert-level understanding of that behavior, I would still rather code using GetAsBoolean() to make things certain for me, and clear for others.