Oxygene Coding Style

What I suggested we do is clean these up as we touch the code. i.e. when updating/extending/fixing code that doesn’t follow conventions, adjust it; but other than that, going there all code for this seems like a lot of effort for little gain, esp. since making the field and var name consistent would be entirely manual…

It’s what I do in the core Elements code base myself (some of which has truly atrocious spacing, don’t tell @ck I said that ;)…

2 Likes

As a new learner of Oxygene, most of my knowledge of Pascal is garnered through Lazarus/Free Pascal/Delphi and there has been quite a few ‘gotchas’ as a new learner unfamiliar with C# syntax. I’ve found it has been most helpful to learn C# in order to learn Oxygene. I’m not sure if others have encountered the same issues coming from another dialect of Pascal. But here are some simple examples of my findings:


Delphi:
var value : Double;
readLn(value); <=== this will create a ‘No matching overload’ error in Oxygene.

Oxygene:
var value := Double.Parse.readLn();


Delphi:
writeLn(‘So you’'re ', age, ’ years old. And your GPA is ', gpa:0:1); <=== this will create an error in Oxygene

Oxygene:
writeLn($“So you’re {age} years old and your GPA is {gpa}.”); //C#-style string interpolation syntax

or

writeLn(‘So you’'re ’ + age + ’ years old and your GPA is ’ + gpa + ‘.’);


You can declare a block of variables using ‘var’ once in Delphi.
var
value : Integer;
gpa: Double;

In Oxygene, it appears each variable must be declared individually:
var value: Integer;
var gpa: Double;

Curious; I was not aware of those API variations. I suppose we could support most, except the writeLn() with multiple parameters; that would conflict without our existing writeLn() overload in Elements RTL that takes a format string (and optional parameters)…

Both work in Oxygene, but IMHo inline variables are better, as they allow yu to declare variables where needed, and initialize them with previous content, rather than having to declare them all on one huge block at the top.

I agree with declaring variables when needed. But when you use ReadLn in Delphi, Free Pascal or even PascalABC.Net, you cannot declare a variable at the same time as user input with ReadLn … the variable must be declared beforehand. Admittedly I like the way Oxygene does it better, more modern. By the way, the creators of PascalABC.Net mention Oxygene in their help files (albeit in Russian). They state that Oxygene is close in ideology to PascalABC.Net :smiley: … I had to translate it from Russian.

Declaration of a block of variables doesn’t appear to work in Oxygene though. Anything after the first statement or semi-colon is not read as a variable it seems :confused:

Move the var block between class method … and begin. Like in old school pascal.

in Oxygene you can now use out var to declare a variable as part of a call that takes an out parameter (of course for true in or var you need to declare it beforehand, but IMHO its still better to do that just the line before ;).

e.g:

GetValue(our var lNewVariable);
lNewVariable.DoSomething;

:pray:t3:

interesting haven’t looked at that project in a while; I should have another look.

Sure that works in Delphi, after the begin? usually the var block in classic pascal was before the begin, and that should be supported in Oxygene.

In your example, after the first ;, how should the compiler distinguish between a second variable declaration and a regular statement (age:Integer could be a method call, for example)…

1 Like

Hi tKautz, thank you for chiming in. It appears when I follow your suggestion, then I get ‘implementation missing’ error :-/

Ah yes. var blocks only work in “classic” split mode with the implementation outside of the class declaration. Because otherwise this is indistinguishable from a method header and 3 fields.

1 Like

Marc, I’m not quite sure what “classic” split mode means , but it sounds good. :smile: is it safe to say that one could also simply declare each variable separately after the Main ‘begin’ or implement inline variables when needed as you suggested? I could get my program to compile by declaring each variable separately after the ‘Main begin’ in this case.

In Delphi, and Oxygene until 2 or 3 years go, only the method declaration goes into the classend block. the behind body had to go into a separate implementation section below it. Ww support var blocks for this, but not when having the whole method body inside the class definition (what we call “unified” class syntax), because its ambiguous:

method Foo;
var x: String;

if this a method header, implemented later, and a field, or is it a var block for the method? the compiler can’t tell, so we only allow it to be the former.

Correct, yes. that;'s the way to do it though (my personal preference) i would move the individual var declarations down to where the var is first needed, rather than declare them all at the top; especially for more complex/larger methods.

1 Like

Thank you Marc for taking time to explain ‘classic’ split mode! :pray: And concerning inline variable declarations, I just noticed it’s in the documentation that I’m pouring over … still have much to learn about Oxygene. :nerd_face:

Inline vars and Type Inference

Most prominently, Oxygene does away with the need for an explicit var section at the top of each method where all the method’s local variables need to be declared.

Instead, Oxygene lets you declare variables throughout the flow of your method where they are needed, with the new var statement. This makes code easier to understand, as variables can be declared closer to where they are used, and even inside nested scopes, such as if blocks or Loops.

More importantly, the var statement supports type inference, so you can, for example, assign the result of a method call to a new local variable without restating (or even knowing) the exact type. Variables defined with inferred type will of course still be strongly typed.

1 Like

Hey Marc,
So it does appear that it’s possible to place a block of variables between the Main and begin when using the NetCore (vs Classic.Net template previously shown). Of course, I will still declare my variables inline or closer to where they’re needed. Cool that it works though :nerd_face:

2021-03-15 23_06_17-Cons_Oxy_NetCore.sln - Water

This has nothing to do with platform. it works if the method body is in the implementation section; it will not work if it’s inside the class declaration, unified style, because that would lead to ambiguity.

1 Like

A following up question - what is the official RemObjects C# style? The same as Microsoft C# where all the curly braces start on a new line? Or similar to Oxygene?

We don’t have one, but I myself use the curly on a new line, matching up the open and close. its the only sane thing IMHO.

1 Like

So that is Microsoft C# style?

1 Like

:scream: Why would you then want the begin on the same line in Oxygene ?

why would you ever possibly not? consider;

if somethinng then bla;
begin
end;

....

if somethinng then
begin
end;

that’s just wrong. the end has to line up with the if.

I believe so, yes.

It’s possible that the C#-style newline opening and closing braces may be more due to to the influence of Anders Hejlsberg, the creator of both Delphi and C#.