Because the and with variants is not like a regular and with boolean expressions but rather a function that takes two Variants and returns a boolean (see System.Variants._VarAnd). And then it is clear why both expressions need to be evaluated first. This is also not limited to Variants but applies to operator overloads as well (even if one of the operands is a boolean).
And that also happens, if only one value being compared is variant. Something like: procedure Test; var X: Variant; O: TMyClass; begin X := True; O := nil; if (X = True) and (O <> nil) and O.IsSomething then DoSomething; end;
Virgo Pärna That is not correct. The evaluation stops after the nil check for O.
It would call IsSomething if you write: if X and (O <> nil) and O.IsSomething then
because then one expression is of type Variant and thus all other expressions are being turned to a Variant. If you do (X = True) the result is of type Boolean and the short-circuit evaluation takes place.
Stefan Glienke Yeah, I might remember it incorrectly. But what is really strange, is, that I remember running into this problem. But right now I cannot create this problem. Weird. Even when using if X and (O <> nil) and O.IsSomething then
Ok, my problem was, that I assumed, that callin nil.IsSomething will result in Access Violation. When I changed test code to output message when IsSomething is called, then it started to show the issue.
I guess the reason it works like this is, that in the case of Variant it does not know at compile time, if it is boolean or bitwise operation. So it needs to evaluate all values. But simply casting Variant to Boolean works.
Virgo Pärna Yes, the implicit type conversion is the problem. Because every boolean expression is being cast to variant to perform the boolean operator on two Variants. If you cast the Variant to a Boolean then the short-circuit evaluation can take place.
Sorry, I don't quite understand...?
ReplyDeleteShow us the code...
ReplyDeleteWhat code is there to show?
ReplyDeleteIf either operand involves a Variant, the compiler always performs complete evaluation (even in the {$B} state).
ReplyDeletefrom first Embarcadero result in Google search:
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/expressions_xml.html
function A:Variant... end function B:Variant... end ... A and B ... Both functions will always be called, versus just calling A when it returns True
ReplyDeleteBecause the and with variants is not like a regular and with boolean expressions but rather a function that takes two Variants and returns a boolean (see System.Variants._VarAnd). And then it is clear why both expressions need to be evaluated first.
ReplyDeleteThis is also not limited to Variants but applies to operator overloads as well (even if one of the operands is a boolean).
FWIW: https://quality.embarcadero.com/browse/RSP-15470
And that also happens, if only one value being compared is variant.
ReplyDeleteSomething like:
procedure Test;
var
X: Variant;
O: TMyClass;
begin
X := True;
O := nil;
if (X = True) and (O <> nil) and O.IsSomething then
DoSomething;
end;
Will always access O.IsSomething
Virgo Pärna That is not correct. The evaluation stops after the nil check for O.
ReplyDeleteIt would call IsSomething if you write:
if X and (O <> nil) and O.IsSomething then
because then one expression is of type Variant and thus all other expressions are being turned to a Variant. If you do (X = True) the result is of type Boolean and the short-circuit evaluation takes place.
Stefan Glienke
ReplyDeleteYeah, I might remember it incorrectly. But what is really strange, is, that I remember running into this problem. But right now I cannot create this problem. Weird. Even when using if X and (O <> nil) and O.IsSomething then
Ok, my problem was, that I assumed, that callin nil.IsSomething will result in Access Violation. When I changed test code to output message when IsSomething is called, then it started to show the issue.
ReplyDeleteI guess the reason it works like this is, that in the case of Variant it does not know at compile time, if it is boolean or bitwise operation. So it needs to evaluate all values. But simply casting Variant to Boolean works.
Virgo Pärna Yes, the implicit type conversion is the problem. Because every boolean expression is being cast to variant to perform the boolean operator on two Variants. If you cast the Variant to a Boolean then the short-circuit evaluation can take place.
ReplyDelete