There is an entire section in the manual discussing the differences between 4tH and Forth - and explaining WHY they are different:
Booleans
Another nice topic for a flame war is the value of truth. In ANS-Forth the 'TRUE' has the value "-1", which means all bits are set. Which is very clever. You can 'XOR', 'OR', 'AND' and 'INVERT' it with any other value and it will behave as logical value. But "the all bits set" flag has its drawbacks too. Let's see what the ANS-Forth standard says about flags:
"A FALSE flag is a single-cell datum with all bits unset, and a TRUE flag is a single-cell datum with all bits set. While Forth words which test flags accept any non-null bit pattern as true, there exists the concept of the well-formed flag. If an operation whose result is to be used as a flag may produce any bit-mask other than TRUE or FALSE, the recommended discipline is to convert the result to a well-formed flag by means of the Forth word 0<> so that the result of any subsequent logical operations on the flag will be predictable. In addition to the words which move, fetch and store single-cell items, the following words are valid for operations on one or more flag data residing on the data stack: AND OR XOR INVERT"
We highly recommend the discipline of converting a non-zero value to a well-formed flag. But we don't understand why 'INVERT' is a valid way to manipulate a flag. We'll try to explain you why.
Forth traditionally has no specific logical operators. Instead, binary operators were used. This put 'INVERT' (or 'NOT' as it was called in Forth-79) in a difficult position. 'INVERT'ing any non-zero value will result in a non-zero value, except when all bits are set.
That is why '0=' was introduced, a full-fledged logical operator. So why use 'INVERT' when you want to perform a logical operation? Another quote:
"Since a "char" can store small positive numbers and since the character data type is a sub-range of the unsigned integer data type, C! must store the n least-significant bits of a cell (8 <= n <= bits/cell). Given the enumeration of allowed number representations and their known encodings, "TRUE xx C! xx C@" must leave a stack item with some number of bits set, which will thus will be accepted as non-zero by IF."
This is another problem of using "all bits set" as a true flag: you store a well formed flag in an address unit that should easily be able to handle it and you'll never get it back. A flag is a boolean and can have two values: either true or false. The smallest unit that can hold a boolean is a bit. ANS-Forth programmers are denied that privilege.
But why are some Forth programmers so keen on their “all bits set” flag? Well, you can do neat things with it.
: >CHAR DUP 9 > 7 AND + ASCII 0 + ;
This will convert a digit to its ASCII representation. True, it is a clever piece of programming, but in our opinion it is bad style. Why? Because you are using a flag as a bitmask, which is a completely different datatype. Although there is no such thing as “data typing” in Forth, this way of programming makes it difficult to understand and maintain a program, which the ANS-Forth standard acknowledges:
"The discipline of circumscribing meaning which a program may assign to various combinations of bit patterns is sometimes called data typing. Many computer languages impose explicit data typing and have compilers that prevent ill-defined operations. Forth rarely explicitly imposes data-type restrictions. Still, data types implicitly do exist, and discipline is required, particularly if portability of programs is a goal. In Forth, it is incumbent upon the programmer (rather than the compiler) to determine that data are accurately typed."
But there is an even more compelling reason why 4tH returns ”1” as
the 'TRUE' value. ”-1” is only valid in a 2-complement context. What it actually means is ”all bits set”. Mathematically it means
nothing, contrary to ”1”, which is return value associated with the Iverson bracket (
https://en.wikipedia.org/wiki/Iverson_bracket).
.
That is why 4tH uses "1" as a true flag. Usually, it won't make much difference. Except when you use 'INVERT' to invert a flag or intend to make obfuscated programs. If you use '0=' instead, you won't run in any trouble, not even when you port your program to ANS-Forth. Clarity may introduce a little overhead, but in this age of multi-gigaherz machines, who is counting? E.g. you could program “>CHAR” like this:
\ convert a flag to a bit mask
: >MASK 0 SWAP IF INVERT THEN ; ( f -- mask)
\ convert a digit to ASCII
: >CHAR DUP 9 > >MASK 7 AND + ASCII 0 + ; ( n -- c)
If you still want to change the true flag, you can by simply changing a #define in cmds_4th.h:
But we doubt whether it will be a great benefit to your programming style.