Jump to content
Marco Cantu

Inline Variables Coming in 10.3

Recommended Posts

1 hour ago, Stefan Glienke said:

A few closures are not functional programming 🙂 Even less so if they are not pure.

Yes, you can borrow a fraction of concepts from FP but you cannot do FP in a non FP language.

OK, let's call it functional programming elements in an imperative language. In 10.3 and subsequent releases these elements will be even more.

Share this post


Link to post

When i read Marco's blog post the first time, i just was afraid. It thought, that this will making code more chaotic and it will going into the direction of PHP (using variables without declaration).

 

In the meanwhile, i read the post a second time and had time to thing about this new language feature.

 

And came to the conclusion that there are more situations, where this features is usefull, because its clarifiying code. You do not have to jump

around, to see where a variable is declared. Also it gives us a new method for using temporary objects.

 

So, imho its like with all new features. It has its advantages but also its disadvantages.

Share this post


Link to post
7 hours ago, Stefan Glienke said:

Inline variable declaration and type inference has nothing to do with FP at all.

I just noticed that these innovations will make the functional elements in Delphi code more compact and easy to understand.

 

And if we talk about functional programming, please look at this article by Joel Spolsky ("Can Your Programming Language Do This?"). We can write code in the same style, and after 10.3 we will be able to remove unnecessary syntax elements, while maintaining strong typing of Delphi language. 

Share this post


Link to post

Marco write:

Quote

Initializing Inline Variables

A significant change compared to the old model, is that the inline declaration and initialization of a variable can be done in a single statement. This makes things more readable and smoother compared to initializing several variables at the beginning of a function.

procedure Test; // declaration and initialization in a single statement
begin
  var I: Integer := 22;
  ShowMessage (I.ToString);
end;

Why not go one step further and allow initializing local variables?

 

IMHO will be nice to type:

procedure Test;
var
  lLastName: string := 'Type last name here';
begin
  lLastName := InputLastNameThere(lLastName);
end;

Of course, this will be a syntactic sugar, because compiler must add  lLastName := 'Type last name here'; at the first line after begin

Edited by Markus Kinzler
Changed formatter to Pascal

Share this post


Link to post
2 hours ago, Stregor said:

Why not go one step further and allow initializing local variables?

Because that would only make initializing with const values possible and not like now initializing with function results.

So I guess their reasoning was to not extend existing variable declaration in a very limited way but go the full distance.

Share this post


Link to post

{$ENDIF Something}?

 

Rather:

 

procedure DoesSomething;
var
  var1: Integer;
  {$IFDEF Something}
  {$IFNDEF DXE103UP}
  var2: Integer;
  {$ENDIF}
  {$ENDIF}
begin
  // use var1
  {$IFDEF Something}
  {$IFDEF DXE103UP}
  var var2: Integer;
  {$ENDIF}
  // use var1 and var2
  {$ENDIF}
end;
 

How many of you can start using the new syntax without paying attention?

 

  • Like 2

Share this post


Link to post

Using that feature in code that also needs to compile in versions before 10.3 makes no sense - however once we migrate to a version that has this feature I will use it in company source code with great joy.

  • Like 5

Share this post


Link to post
3 hours ago, Attila Kovacs said:

Even if it breaks your Uses Helper for long time?

It will only break it as long as DelphiAST does not support the new syntax 🙂

Share this post


Link to post

Can't wait for the new release. How about complex structures, is it possible?

// Before Delphi 10.3
function TestInlineArray: string;
var
  strArray: array of string;
begin
  strArray := ['Delphi', 'JavaScript', 'Python', 'PHP', 'C'];
  Result := strArray[Random(5)];
end;
// Inlining
function TestInlineArray2: string;
begin
  var strArray := ['Delphi', 'JavaScript', 'Python', 'PHP', 'C'];
  Result := strArray[Random(5)];
end;

Who can answer? Simple + or - would be OK. :)

Share this post


Link to post

I found another case where inline variables will be useful - as substitution for a with statement. Yes I know: nowadays no one use them... (Just kidding, I found with statements even in the Delphi 10.2.3 source folder).

with ControlRange as IHTMLControlRange do
begin
  select;
  execCommand('Cut', False, EmptyParam)   { do not localize }
end;

After 10.3 it can be replaced with

begin
  var cr := ControlRange as IHTMLControlRange;
  cr.select;
  cr.execCommand('Cut', False, EmptyParam)   { do not localize }
end;

So the with statement can be finally deprecated and excluded from the language.

Or maybe we will can write:

with var cr := ControlRange as IHTMLControlRange do
begin
  cr.select;
  cr.execCommand('Cut', False, EmptyParam)   { do not localize }
end;

 

Edited by Kryvich

Share this post


Link to post

Or even better to enchance the with statement as follows:

with const cr := ControlRange as IHTMLControlRange do
begin
  cr.select;
  cr.execCommand('Cut', False, EmptyParam)   { do not localize }
end;

"const cr" because inside the statement cr is used only to access its members.

  • Like 1

Share this post


Link to post

This is awesome. Thank you.

 

Reducing the scope of a variable is very good practice.

 

One question, inline constants - can they be assigned by function calls or need to be compile time evaluted? If only the latter then F.

 

 

Share this post


Link to post
7 minutes ago, Davor Slutej said:

One question, inline constants - can they be assigned by function calls or need to be compile time evaluted? If only the latter then F.

Marco says in his blog post:

Quote

Beside variables, you can now also inline a constant value declaration

So I think constant value expressions are evaluated at compile time. But I would love to see inline constants initialized with dynamic values just like in TypeScript.

Share this post


Link to post

@dados The right side of assignment can be any statement of a type that has members. Of course it can be the function call that returns an object or a record as well. This extended with statement should prompt the compiler to create a temporary readonly variable cr, without increasing the count of references, for optimization purposes.

 

Note: it's just my suggestion how to make a with statement more convenient and useful for a programmer and Delphi compiler. I am not participating in Delphi Beta testing, and I don’t know if they made any changes to this statement.

Edited by Kryvich

Share this post


Link to post

Next example of use inline variable to improve code clarity:

 

Instead of unclear:

 

 

fRecipients := TCollections.CreateList<TRecipient>(True);

 

we can write:

 

  fRecipients := TCollections.CreateList<TRecipient>(var OwnsObjects = True);

 

Edited by Jacek Laskowski

Share this post


Link to post

@Jacek Laskowski To improve clarity it is better to use enumerated types instead of generic types such as Boolean, Byte, Integer.

// In library:
type TOwnsObjects = (No, Yes);
// User code:
fRecipients := TCollections.CreateList<TRecipient>(TOwnsObjects.Yes);

This will require changes in a framework code, but will not require complicating a syntax of the language.

Edited by Kryvich

Share this post


Link to post
7 hours ago, Wosi said:

Marco says in his blog post:

So I think constant value expressions are evaluated at compile time. But I would love to see inline constants initialized with dynamic values just like in TypeScript.

Well, this works:

begin
  var I := 20;
  const J = I-1;
  Writeln('I=', I);
  Writeln('J=', J);
end;

 

  • Thanks 1

Share this post


Link to post
On 11/1/2018 at 9:43 AM, Stefan Glienke said:

It will only break it as long as DelphiAST does not support the new syntax 🙂

I'm hoping DelphiAST is updated to handle it soon after Rio is released (or beforehand) :-)

Share this post


Link to post
12 hours ago, Uwe Raabe said:

Well, this works:


begin
  var I := 20;
  const J = I-1;
  Writeln('I=', I);
  Writeln('J=', J);
end;

 

Great! What's about this:

const RESTClient = TRESTClient.Create(Nil); 

Does it work?

10 hours ago, Dave Nottage said:

I'm hoping DelphiAST is updated to handle it soon after Rio is released (or beforehand) :-)

I'm having a good feeling about it 😉

https://github.com/RomanYankovsky/DelphiAST/pull/271

Edited by Wosi
  • Like 2

Share this post


Link to post
1 hour ago, Wosi said:

const RESTClient = TRESTClient.Create(Nil); 

Does it work? 

Hard to imagine, given that the result of TRestClient.Create(..) is not known at compile-time. This would not be a "const", but a readonly variable. Maybe one day Delphi will also have that?

Edited by Der schöne Günther

Share this post


Link to post
1 hour ago, Wosi said:

Great! What's about this:


const RESTClient = TRESTClient.Create(Nil); 

Does it work?

At least it compiles...

  • Like 1

Share this post


Link to post
On 10/29/2018 at 10:35 AM, Sherlock said:

Could someone please explain the benefit of type inference in a programming language that showcases type safety? As soon as the compiler has to guess a type, and my be wrong, this could result in C-like problems later on. I have made my peace with inline variables (yes, I am quick at giving up), but this feature seems a bit too "over the top" bait for non Delphi developers. I mean, this too can be ignored, but with a team big enough, it just find it's way into code nevertheless.

The type is still safe. It just doesn't have to be repeated (IOW, you get DRY).  So instead of

 

    var

      X: TObjectList<MyUsefultype>;

   begin

      X := TObjectList<MyUsefulType>.Create;

 

You simply do:

 

    begin

       var X := TObjectList<MyUsefulType>.Create;

 

The compiler does not guess. Type inference is not new either. You already had it for true constants and for certain generic functions (if the compiler could determine the type parameter, you don't have to specifiy it). You also had it when declaring a variable using Refactoring. Now you have it in the compiler. They type is not "guessed", it is determined. Also, if you do:

 

    var i := 17;

 

then i is not a byte. The compiler chooses a useful type, in this case Integer. If you want something else but the default, you can do:

 

    var i: UInt32 := 17;

 

so then you don't use type inference.

 

It makes declaring types a lot simpler and doesn't require repetition, which means there is less chance for errors. I wish we had had it much earlier. These things: inline declaration, inline initialization, block local scope and type inference are all one new feature and belong to each other. 

Edited by Rudy Velthuis
  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×