[BUG] ?? in True and False

Richard A. O'Keefe ok at cs.otago.ac.nz
Fri Mar 14 05:04:35 UTC 2003


	Since #and: and #or: do not promise to evaluate their arguments, the
	fact that they do not determine whether they are Booleans or not does
	not seem like a bug.

In fact, #and: and #or: *DO* evaluate their argument (sometimes)
and #& and #| *NEVER* evaluate their argument.
On the contary, when control arrives at #& or #| the argument
has already been evaluated.

	If you do not evaluate them, how do you know?

Strictly speaking, #and: and #or: don't evaluate their argument either.
They send it the #value message (sometimes),
and it is just plain confusing to call that "evaluation".

My point is that the ANSI standard says the SAME thing about #and: and #or:
(returns a <boolean>) as it does about #& and #|.  If it is a bug for one
of them, it is a bug for all of them.  If you DO send #value to the block
argument, you DO know.

	And, as far as I can tell by looking at the method code, & and | do not
	live up to that promise, anyway. Shouldn't they?
	
Traditionally, they shouldn't be MAKING that promise, is all.
Historically, Smalltalk never has enforced a restriction on the argument
of #& and #| (or the result of sending #value to the argument of #and: and
#or:).  ANSI Smalltalk doesn't exactly says it's *illegal* to return
non-Boolean, just that the effect is undefined, and Squeak is free to
define it to be the way it has been since 1972.

    True>>& alternativeObject 
      "Evaluating conjunction --
       answer alternativeObject since receiver is true."
      ^alternativeObject

Comment is misleading (& doesn't do any evaluation that + doesn't)
but otherwise accurate.  Argument name couldn't say more clearly
that it doesn't have to be Boolean.

    True>>| aBoolean 
      "Evaluating disjunction (OR) --
       answer true since the receiver is true."
      ^self

Comment is misleading (| doesn't do any evaluationg that + doesn't)
but otherwise accurate.  Argument name is misleading since it suggests
falsely that it should be aBoolean.  Rewrite as

    True>>| alternativeObject

with the same body.

    False>>& alternativeObject 
      "Evaluating conjunction --
       answer false since receiver is false."
      ^self

Comment is misleading (& doesn't do any evaluation that + doesn't)
but otherwise accurate.  Argument name couldn't say more clearly
that it doesn't have to be Boolean.

    False>>| aBoolean 
      "Evaluating disjunction (OR) --
       answer with the argument, aBoolean."
      ^aBoolean

Comment is misleading (| doesn't do any evaluation that + doesn't)
and suggests something false, that the argument must be Boolean.
The argument name should be the same for | as for &

    False>>| alternativeObject	
      "Evaluating disjunction (OR) --
       answer alternativeObject since the receiver is false."
      ^alternativeObject

Note that some Smalltalks make a special case of methods with the form	
    <heading>
      ^self
    <heading>
      ^anInstanceVariable
    <heading>
      ^aMethodArgument
(not sure about the last of these, but why not?) so that calling them
is extra fast.  I don't know what Squeak does with such methods.

To make this stuff check for Boolean-ness, you'd have to do something
like

    False>> & aBoolean    aBoolean not not. ^self
    False>> | aBoolean    ^aBoolean not not
    True>>  & aBoolean    ^aBoolean not not
    True>>  | aBoolean    aBoolean not not. ^self

which is still vulnerable to redefinition of #not.  Best we could do would
be a new reserved method #NOTNOT understood by the compiler and generating
a 'check if Boolean' bytecode, so

    False>> & aBoolean    aBoolean NOTNOT. ^self
    False>> | aBoolean    ^aBoolean NOTNOT
    True>>  & aBoolean    ^aBoolean NOTNOT
    True>>  | aBoolean    aBoolean NOTNOT. ^self

and then
    e1 and: [e2]
would compile to something like
    e1. jump-if-false L.
    e2. NOTNOT.
L:
to get the Boolean check there.

To "fix" this "bug",
- the documentation must be changed
- the VM needs to implement a new NOTNOT bytecode
- the compiler needs to be changed to emit it for #and: and #or:
  (unless #and: and #or: are to be inconsistent with #& and #|
  which is surely highly undesirable)

This is a lot more work than just
+ fixing the documentation.

To justify it, there needs to be sufficient benefit.

I haven't seen an argument that the benefit is noticeable, let alone
worthwhile.  How many people have bugs in their code that would be
found a lot earlier with this change?  How many of those people are
happy for e1 and: [e2] to run slower (when e1 is false)?

I'm sure this issue was thrashed to death a year or two ago (too close
to going-home time to search the archives); didn't we agree on a
documentation clarification back then?



More information about the Squeak-dev mailing list