[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
|