True and False

**************************************
***** Stata Self-Learning Course *****
****** University of Goettingen ******
**************************************
******** Advanced Programming ********
******* True and false in Stata ******
**************************************

/* 
The easiest way to think about "true" and "false" in Stata is to think about "1"
and "0". Consider a binary variable which indicates whether an observation is
within the lowest third in the range of observations:
*/

clear all
set obs 100

gen lower_third = (_n<=33)
/*
This variable will be 1 if the observation belongs to the first 33 observations
and 0 otherwise. For us, and for Stata, this translates into "true" and "false":
The statement "_n<=33" is true for the first 33 observations, so these will be 
assigned to the value "1". The statement "_n<=33" is false for all other 
observations, so these will be assigned to the value "0". You have worked with
this logic before, but maybe without realizing it yet. To summarize, Stata and us,
we agree on the following convention:
	0	False
	1	True
*/
// Thus, typing
count if lower_third==1
// is equivalent to
count if lower_third
// in the case of a binary variable. We will get to the more complex case below.
// Both ask Stata to count the number of observations if lower_third is "true",
// i.e. if lower_third==1

// Similarly, typing
count if lower_third==0
// is equivalent to
count if !lower_third
// Both ask Stata to count the number of observations if lower_third is "false",
// i.e. if lower_third==0. Note that the "!" stands for "(is) not" in Stata.



/*
However, Stata has also a more complicated way of defining "true" and "false".
Namely, it considers not only 1, but ANY value !=0 as "true". This might be
confusing sometimes. Consider the following categorical variable.
*/

gen thirds = .
replace thirds = 1 if _n<=33
replace thirds = 2 if _n>33 & _n<=66
replace thirds = 3 if _n>66
// As for all observations the variable is !=0, the number of observations for which
// thirds is "true" equals the number of all observations.
count if thirds
count if !thirds
// Though counterintuitive, this means that missings are also !=0, or "true"
replace thirds = . if _n==100
count if thirds
count if !thirds
// Similarly, values<0 are also !=0, or "true"
replace thirds = -1 if _n==100
count if thirds
count if !thirds


/*
What does this mean for our programming?

1. Commands like assert, confirm or isid
These commands test a certain expression, and issue an error code if the test is
false. The object _rc will contain the current error code (it is a special type
of object, but think of it as if it was a scalar from the return list for now).
So, if the test worked, the error code will contain "0" - there is no error to
be issued, or in other words, the existence of an error is "false". If the test
did not work, an error will be issued and the according error code will be filled
in the object _rc. You can see the exact number in the error message (for example, 
if you simply type "count test", the error code will be 101). Important for now
is only that whatever the number is, it will be !=0, i.e. the existence of an
error is "true". We can use this output in _rc to branch in our code.

2. If-branching
As shown above, when the test is always ==0 against !=0, so "false" against "true",
we can be lazy and type e.g.
	count if lower_third
when we mean 
	count if lower_third==1
respectively 
	count if !lower_third
when we mean
	count if lower_third==0
This is helpful when branching on the basis of _rc, but also when branching on any
other expression or variable we know to be 0 when "false" and !=0 when "true". For
example, many string functions return 1 if the tested expression is "true", and 0 
if it is "false". Similarly, the temporary variable which is created by the marksample
command (conventionally named as `touse'), will be 0 if the observation should not
be used, and !=0 otherwise. So, if we want to summarize a variable based on the 
information stored in `touse', we can simply type
	count `variable' if `touse'	
Important: This will NOT work as intendend if the variable/object has other values
than 0 and 1 (e.g. missings) which you do not consider to be "true". Then, you
need to go back to spelling it out, i.e. if thirds==1
*/
			

Further reading

You might also consider this post helpful: https://www.stata.com/support/faqs/data-management/true-and-false/

For more on error codes, you can look into the help file/ manual for "capture".