AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Delphi-PRAXiS - Lounge Delphi-News aus aller Welt Introducing Inline Variables in the Delphi Language
Thema durchsuchen
Ansicht
Themen-Optionen

Introducing Inline Variables in the Delphi Language

Ein Thema von DP News-Robot · begonnen am 29. Okt 2018
Antwort Antwort
Benutzerbild von DP News-Robot
DP News-Robot

Registriert seit: 4. Jun 2010
15.392 Beiträge
 
#1

Introducing Inline Variables in the Delphi Language

  Alt 29. Okt 2018, 12:20
The Delphi language in 10.3 has a fairly core change in the way it allows far more flexibility in the declaration of local variables, their scope and lifetime. This is a change that breaks a key tenet of the original Pascal language, but offers a significant number of advantages, reducing unneeded code in several cases.

Old Style Var Blocks*

Since Turbo Pascal 1 and until now, following classic Pascal language rules, all local variable declarations had to be done in a var block written before the beginning of a function, procedure or method:

procedure Test; var I: Integer; begin I := 22; ShowMessage (I.ToString); end; Inline Varaible Declarations

The new inline variable declaration syntax allows you to declare the variable directly in a code block (allowing also multiple symbols as usual):

procedure Test; begin var I, J: Integer; I := 22; j := I + 20; ShowMessage (J.ToString); end; While this might seem a limited difference, there are several side effects of this change. It is these additional effects that make the feature valuable.

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; More over, if the value of a variable is available only later in the code block, rather than setting an initial value (like 0 or nil) and later assign the actual value, you can delay the variable declaration to the point you can calculate a good initial value:

procedure Test1; // multiple inline declarations (symbols declared when used) begin var I: Integer := 22; var J: Integer := 22 + I; var K: Integer := I + J; ShowMessage (K.ToString); end; In other words, while in the past all local variables where visible in the entire code block, now an inline variable is visible only from the position of its declaration and up to the end of the code block.

Scope and Lifetime of Inline Variables Declared in Nested Blocks

The scope limitation is also more relevant as is doesn't apply to the entire procedure or method, but only to the begin-end code block the inline variable appears. In other words, the scope of an inline variable is limited to the declaration block and the variable cannot be used outside of the block. Not only, but the variable lifetime is also limited to the block. A managed data type (like an interface, string or managed record) will now get disposed at the end of the sub-block, rather than invariably at the end of the procedure or method.

procedure Test2; // scope limited to local block begin var I: Integer := 22; if I > 10 then begin var J: Integer := 3; ShowMessage (J.ToString); end else begin var K: Integer := 3; ShowMessage (J.ToString); // COMPILER ERROR: "Undeclared identifier: J" end; // J and K not accessible here end; As you can see in the last code snippet above, a variable declared inside a begin-end block is visible only in the specific block, and not after the block has terminated. At the end of the if statements, J and K won’t be visible any more.
</br> As I mentioned, the effect is not limited only to visibility. A managed variable, like an interface reference or a record, will be properly cleaned up at the end of the block, rather than at the end of the procedure or method:

procedure Test99; begin // some code if (something) then begin var Intf: IInterface = GetInterface; // Intf.AddRef var MRec: TManagedRecord = GetMRecValue; // MRec.Create + MRec.Assign UseIntf(Intf); UseMRec(MRec); end; // Intf.Release and MRec.Destroy are implicitly called at end of scope // more code end; // no additional cleanup Type Inference for Inline Variables

Another huge benefit of inline variables is that the compiler now can, in several circumstances, infer the type of an inline variable*by looking to the type of the expression or value assigned to it:

procedure Test; begin var I := 22; ShowMessage (I.ToString); end; The type of the r-value expression (that is, what comes after the :=) is analyzed to determine the type of the variable. Some of the data types are “expanded” to a larger type, as in the case above where the numeric value 22 (a ShortInt) is expanded to Integer. As a general rule, if the right hand expression type is an integral type and smaller than 32 bits, the variable will be declared as a 32-bit Integer. You can use an explicit type if you want a specific, smaller, numeric type.

Now while this feature can save you a few keystrokes for an Integer or a string, variable type inference becomes fairly nice in case of complex type, like instances of generic types. In the code snippet below, the types inferred are TDictionary*for the variable MyDictionary and TPair*for the variable APair.

procedure NewTest; begin var MyDictionary := TDictionary.Create; MyDictionary.Add ('one', 1); var APair := MyDictionary.ExtractPair('one'); ShowMessage (APair.Value.ToString) end; Inline Constants

Beside variables, you can now also inline a constant value declaration. This can be applied to types constants or untyped constants, in which case the type is inferred (a feature that has been available for constants for a long time). A simple example is below:

const M: Integer = (L + H) div 2; // single identifier, with type specifier const M = (L + H) div 2; // single identifier, without type specifier For Loops With Inline Loop Variable Declaration

Another specific circumstance in which you can take advantage of inline variable declarations is with for loop*statements, including the classic for-to loops and modern for-in loops:

for var I: Integer := 1 to 10 do ... for var Item: TItemType in Collection do... You can further simplify the code taking advantage of type inference:

for var I := 1 to 10 do ... for var Item in Collection do ... This is a case in which having the inline variable with limited scope is particularly beneficial, as in the sample code below: Using the I*variable outside of the loop will cause a compiler error (while it was only a warning in most cases in the past):

procedure ForTest; begin var total := 0; for var I: Integer := 1 to 10 do Inc (Total, I); ShowMessage (total.ToString); ShowMessage (I.ToString); // compiler error: Undeclared Identifier ‘I’ end; Inline Summary

Inline variable declarations, with type inference and local scope,*bring fresh air to the Delphi language. While Pascal source code readability remains a key tenet to preserve, it is important to modernize the language at the core level, removing some of the rust (real or perceived). In case of inline variables, there are so many advantages to depart from the traditional coding style,*that the value is clear.

Still, you can keep your code as is and ask your fellow developers to stick with the traditional declaration: nothing in the existing code or style is wrong, but inline declarations offer you a new opportunity. I already have*trouble going back to older versions of Delphi... just saying.

*



Weiterlesen...
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz