Part of the enjoyable challenge of learning Oxygene is trying to discover what is more C# (.Net/CLI) like or Object-Pascal like. Oxygene appears to have inherited quite a bit from .Net (understandably) such as integer division (10/3 = 3) vs returning a real number as Delphi/Lazarus FPC would do (10/3 = 3.333). Then I came upon the topic of operator precedence in the Oxygene online manual:
I read something similar as well in Marco Cantù’s book Essential Pascal :
Contrary to most other programming languages, the and and or operators have higher precedence than comparison ones. So if you write:
a < b and c < d
the compiler will do the and operation first, resulting in a compiler error. So you should enclose each of the < expressions in parentheses:
(a < b) and (c < d)
So I decided to run a quick test case in Delphi, Lazarus FPC, PascalABC.Net and Oxygene and all resulted in compiler errors except for … Oxygene.
namespace Oxy_precedence;
interface
uses
System.Linq;
type
Program = class
public
class method Main(args: array of String): Int32;
end;
implementation
class method Program.Main(args: array of String): Int32;
begin
var a := 10;
var b := 12;
var c := 5;
var d := 8;
// returns 'The magic happens here.'
if (a < b) and (c < d) then
writeLn('The magic happens here.')
else
writeLn('The magic is not here.');
// returns 'The magic is not here.'
if a < b and c < d then
writeLn('The magic happens here.')
else
writeLn('The magic is not here.');
end;
end.
I was quite surprised that ’ a < b and c < d’ made it through Elements Compiler although it returned a dissimilar result than C#(Hydrogene).
and this is what we call a Double Boolean Comparison, see Arithmetic & Logical Expressions. Basically it checks if the middle operand against there first and the last, a example would be:
Very cool, thanks Marc. I wasn’t quite sure how (b and c) would be evaluated, given that other cousin Pascal languages appear to disallow it in this situation - but it appears that Oxygene does allow a bitwise AND operation to be performed in this case.
I think Delphi & Co would do the same. what they don’t so is the (“a < X < d”), which causes the actual error they emit. the (“b and c”) they will do fine.
This is the test I ran. It’s mostly academic in nature, but I included it for completeness.
namespace OxyPrecedenceNetC1;
type
Program = class
public
class method Main(args: array of String): Int32;
begin
var a := 25;
var b := 12;
var c := 3;
var d := 5;
var e := 5;
(* Bitwise AND operations with integer value returned *)
writeLn(a and b); //returns '8'
writeLn(d and e); //returns '5'
writeLn(a and a); //returns '10
writeLn(b and c); //returns '0'
writeLn(c and d); // returns '1'
writeLn(b and d); // returns '4'
(* Bitwise AND operations allowed by Oxygene in the following *)
if a < (b and c) then
writeLn('a < (b and c)') // 10 < (0) -> False
else
writeLn('no'); // returns 'no'
if (b and c) < d then // (0) < 5 - > True
writeLn('True')
else
writeLn('False');
if (d and e) = e then // (5) = 5 -> True
writeLn('True')
else
writeLn('False');
if (d and e) < e then // (5) < 5 - > False
writeLn('True')
else
writeLn('False');
if (d or e) = e then // (5) = 5 - > True
writeLn('True')
else
writeLn('False');
if (c and d) < (b and d) then // (1) < (4) - > True
writeLn('True')
else
writeLn('False');
if (b and d) < (c and d) then // (4) < (1) - > False
writeLn('True')
else
writeLn('False');
readLn
end;
end;
end.