Community pulse: Delphi’s Killer Feature

Managing variables with ease

Managing variables with ease

The usual “off-line” comment: Guys, we’re preparing FileSuite 2. Many interesting things inside – many bugs fixed, folder constraints more scripting commands and, of course, Shell Events. On of the main themes of this release are the usability issues so feel free to submit your feedback. We hope that we’ll have something to present in 7-10 days. Thanks a lot.

And now back in present: There’s a question on StackOverflow asking What’s your favourite programming language, and its killer feature?

Seeing there that Delphi’s choice is #1 among the answers it seems that Delphi’s killer ‘feature’ is becoming (again) its community.

…but we must not be too confident because we have a lot of work to do in this regard (…now I’m wondering how many team members upvoted there…) but definitely it is a very good sign that we’re unite outside and have a constructive dialog inside.

On the corresponding thread in the delphi.non-technical forum, there’s (once again) a discussion about the var block and the need of a more flexible approach (having inline variables and local loop variables).

My (humble) personal opinion is that the best thing will be a compilation of the the main trends in the nowadays programming languages:

Give the possibility to reduce the variable life while discouraging/disallowing the scattering of variables through the code.

And this can be achieved by allowing the var block to be placed anywhere in the procedure body but its scope to be limited to the next statement only. In fact, this is the standard Pascal behavior because any procedure can be seen as a single statement (ok, a composite one, enclosed between begin / end ). Hence the following structures will be valid:


procedure Foo;
var
  nTimes: integer;

begin
  WriteLn('Enter the upper limit:');
  ReadLn(nTimes);
  var
    i: integer;
    for I := 1 to nTimes do
      WriteLn(i);

  //'i' invalid here

  WriteLn('Done');
end;

procedure Bar;
begin
  //....many lines of code here
  var
    nDOW: integer;
    begin
      if GetWeekDay('Please choose the day of the week', nDOW) then
        case nDOW of
          1: //Mon
          2: //Tue
          //...
        end;
    end;

  WriteLn('Here the temporary nDOW is invalid');
  //...another lines of code
end;

This will allow us to have a much greater power of expression without forcing us, in order to limit the life time of the variables, to write a dozen of local procedures. And all of this without forcing us to scan the code in order to find were are the variables declared. Also, perhaps this feature can be implemented by generating under the hood a local procedure. And if this is possible, then perhaps we can write a cleaner code also in the case of the anonymous procedures:


TThread.Synchronize(myThread, procedure ShowMessage('Boo!')); //a procedure is a *single* statement

… instead of more convoluted…


TThread.Synchronize(myThread, procedure
  begin
    ShowMessage('Boo!');
  end);

…oh well, one can dream… …on the road to the lambdas.

Feel free to comment and vote. (Also, don’t forget the FileSuite – the ones who’re interested)

35 thoughts on “Community pulse: Delphi’s Killer Feature

  1. I think that you should not have that large routines in the first place.

    If you have large code, which can benefit from suggested feature – just break it into smaller routines. This will be the best choice. Your first example may just have PrintNTimes routine – and this will be cleaner and more easy to use solution (okay, now you have more code to type 😀 ). And your second example can be made as function, returnin Integer (with a special value of -1 for “False” result).

    Yes, this feature will allow to do few… um.. cool things, but it also increase (possible) chaos. I mean, that now you may use two different variables with the same name inside one large piece of code – what a great area for tricky mistakes!

    • DK:

      This feature does indeed allow you to “use two different variables with the same name inside one large piece of code.” But really how is that much different from what we already have? We already have “subroutine/this unit/used unit” and “method/class/this unit/used unit” scopes.

  2. DK – EXACTLY!

    “freedom” and “flexibility” in programming languages is shorthand for laziness… “I don’t want to have to bother with having to think about decomposing my procedures into fine-grained units of execution and control… allow me to create rambling, indecipherable stream of consciousness code instead”.

    People are too focussed on the ease of *creating* code and neglect the fact that once the act of creation is done, code spends 99.99% of it’s life in maintenance!

    • Jolyon:

      I agree with you that reading of code is just as important as writing of code.

      I am, however, in favor of this feature. It is one of the things I missed when I switched back from C++ to Delphi.

      It is possible to abuse this feature to make long procedures instead of “decomposing my procedures into fine-grained units of execution and control.” However, it is also possible to use this feature to transform my already decomposed subroutines into even more decomposed subroutines. This is why I want this feature.

    • ““freedom” and “flexibility” in programming languages is shorthand for laziness”

      It seems that most of the IT industry is against you, isn’t it?
      How many programming languages enforces the Pascal style of declaring variables. How many programming languages en vogue today even require to declare a variable with its type? And given this how many complaints do you hear about this from the programmers around the world?
      The market share of the other programing languages is expanding while Delphi’s shrinking. So I think that the reality is against you.
      Anyway, if you don’t like it, don’t use it. And in fact, it wasn’t my idea – we discussed this again and again in .non-technical and (as always) the opinions are split.

      • >>> The market share of the other programing languages is expanding while Delphi’s shrinking
        Umm… I don’t think it’s because of language itself, but rather due some other reasons. Cost, for example 😀

        • Price is only one of the factors. People do spend if they perceive the proper value in a product – even if the value is only the “feel good factor”. Delphi underwent a long period of product issues, slow development, company troubles and lack of an overall vision that destroyed the reputation it build before that. Building a reputation takes a long time, destroying it far less.

        • …hehehe…

          Of course that we know what you mean. 😉

          But, you know, you aren’t entirely correct (or, rather, should I say “exact“?). In fact it is the rapport price / performance which counts.
          If the Delphi would be more advanced nowadays (at the same price) then more people would buy it. And, no, I don’t mean that the above feature is the one who will make the difference, but the innovation will be.

      • I don’t understand why we should change Pascal fundamental ways of working and ape whatever language is cool today. Instead of changing Pascal, change language. Most newer language were born to address the needs of web programmers, most of them writing pieces of code to generate HTML pages, or to script server side operations. Often, quick and dirt programming, and where perfomance are not an issue (or they believe it…)
        None of them was born to build large and complex applications. It is true, times are changed. If in 1991 C or TP were the right tools to write almost every application running on a PC. today they are not. The application gamut became much broader. Bastardizing Delphi “just because language x has feature y, today is cool and I want it” is really the wrong approach. Changes to the language should be part of an comprehensive plan to deliver the best tool for the target applications. Well thought improvements are welcome, just “me too” ones can be really counterproductive.

        • “I don’t understand why we should change Pascal fundamental ways of working and ape whatever language is cool today.”

          There isn’t a language which is cool today. There are all other languages which are cool today. And for example C, C#, Java (etc.) are “cool” from some time now. Also, I don’t think that the above-mentioned languages (and if you want to mention also Objective-C, D, Python) are designed to “writing pieces of code to generate HTML pages, or to script server side operations” only. Basically you’re trying to say that the single ‘var’ block at the beginning (the topic at hand) is the distinctive feature of an enterprise language, isn’t?

          About “me too” – well, this is a very big problem indeed. But we must balance between our (very limited) power to be original (against of the common IT experience) and lowering the entry level of new Delphi users from other languages – like you pointed in your other comment.

          • “Basically you’re trying to say that the single ‘var’ block at the beginning (the topic at hand) is the distinctive feature of an enterprise language, isn’t?”

            No, it’s a distinctive feature of Pascal. Clarity. But Pascal and C/C++ design aims, and Java/C#, or Python/PHP/Ruby, or Javascript are very different. Each have different distinctive features. And some really outgrow their original design aims.

            I see no reason why Delphi should make easier coming from other languages – noone will make the same vice versa. Delphi should keep on improving adding coherent changes with Delphi-Pascal design aims. What for example I do not like of Prims is its design – I often joke that it will have soon more reserved words than available identifiers. I think Hejilsberg in the past made a very good job adding features to Pascal without twisting Pascal design.

  3. DK and Jolyon – EXACTLY! 🙂

    My first thought was: this is a bad code style and is absolutely not needed in short methods (as it should be).
    To have the declaration separated from the method body is the real feature. Good to read, easy to understand and quick to change the declared type.
    In every other language i use, i declare each variable before any single line of code in a method.

    • “In every other language i use, i declare each variable before any single line of code in a method.”
      But the question is: Any other language which you use enforces you to do this?
      And if not, did you wonder why?

      • Is the neighbour’s garden always greener? Why Java enforces everything to be a class while Delphi or C++ do not? Why Python enforces indentation? Do you like those enforcements? Or prefer the Delphi/C++ approach?

        • “Is the neighbour’s garden always greener?”

          Is not one neighbor. We speak about all neighbors.
          🙂
          If one says “you’re sick” – don’t listen.
          If two say that “you’re sick” – go and make your analysis.
          If everybody says that “you’re sick” – go to bed. 🙂

          About Java (and C# FTR): – personally I’m reserved, but many are for a rooted type system. Including guys from the Compiler team. And with arguments.
          About Python: No, I don’t like it. I prefer specific delimiters for a code block which is the standard in the IT industry. And this, for the time being, applies also to the type system: basic data types which aren’t objects alongside to a class hierarchy. While I can understand the advantages of a rooted type system, for the time being I prefer Delphi / C / Python’s approach. When everybody will prove me that a rooted type system is better (in almost any aspect – including speed, memory usage etc.) than the classical way, then I’ll adopt it. But since “the many” say “not yet”, I go with “the many”. There are many other areas in which we must to fight against the current…

        • I’d ask a doctor, not to neighbours… as Kipling said:

          IF you can keep your head when all about you
          Are losing theirs and blaming it on you,
          If you can trust yourself when all men doubt you,
          But make allowance for their doubting too;

          Watch what the other language do – but do not believe they’re right just because they’re newer and trendy.

  4. The begin..end pair is not necessary in procedure Bar. Without them the single statement following the declaration is the if statement (which includes the case statement) which is what you want anyway.

  5. I’m considering the explict requirement to declare something before use as a very cool feature of Delphi. Strict distinction of interface and implementation (it also holds for units and classes, not only variables) is a great advantage. Personally, I didn’t like to see as it would be destroyed.

    The feature, that I REALLY like to see – ability to split class declarations in two parts: put public/protected in interface and put private in implementation.

    >>> The begin..end pair is not necessary in procedure Bar
    If you want to “type less” – why don’t you use C++ then? 🙂

    • I didn’t make my point about the begin..end pair because I am in favor of typing less. Instead, I thought the author was trying to give two examples: one that did not require a begin..end and one that did. I was just pointing out that the second one also did not require one.

      I suppose it was an unnecessary post. Likely I was just trying to immaturely impress the rest of the Delphi community with my (supposedly) impressive intellect!

  6. 1) Restricting scope to the next statement only wouldn’t be wise – and would introduce a subtle behaviour difference from other languages that allow for declaring variables inside the procedure – I don’t see any real advantage.
    2) Generating a procedure means an implicit CALL statement (and thereby stack management and RET call) something you may not want especially in fast loops.
    3) AFAIK, most languages allowing to declare variables anyware use it just as a shorthand – local variable are anyway allocate in the prologue and deallocated in the epilogue. Especially the “pascal” calling convention that uses RET n to deallocate n byte from the stack when exiting needs a fixed amount of stack space to deallocate because n must be a constant. Changing the stack pointers often within a functions would lead to more complex code to be generated.

    • 1) “Restricting scope to the next statement” is already done in Pascal, e.g., the if-then-else statement. I agree it is different from other languages and it does require adjustment for the transitioning programmer.

      3) It is useful to remember that a declaration concerns a variable’s lifetime and its scope. Your point is about the variable’s lifetime. This is an important consideration for the compiler maker. To me, the compiler user, my main concern is where/when is the variable visible. If the compiler maker tells me that it would cost (time, size, etc.) too much to be worth it then I guess I’ll take his word for it and do without the feature.

      • 1) if statements do not restrict scope, because you don’t declare anything within.
        2) I was pointing out that it would be just a shorthand, not an optimization, because the compiler may allocate all variables at the procedure entry point anyway. Does declaring variables near where they are used a better approach of declaring them at the procedure beginning? Maybe, or maybe not. It is a break of Pascal clarity rules. And then, what’s next? Using curly braces instead of the longer begin..end? 🙂

        • 1) If the condition is True, the following statement, not the following block, is executed.

          2) The point of declaration is about more than just code performance. The point of declaration is also about when it is possible to access the variable. One could extend your argument further: “Does declaring variables near where they are used a better approach of declaring them at the program beginning? Maybe, or maybe not.” Therefore it might be better to declare all the variables in the entire program at the beginning of the program? (I don’t think so.)

  7. For me it’s not a “number one” language feature. If it is accompanied with auto allocation/deallocation it would be.

    I mean:

    // here a compiler should add the variable to var section
    with var a: TSomething.Create do
    begin

    // and here it should call a.Free
    end

    And a clear scope indication is a must for me. Either in a form of WITH or alike.

    • This is yet-another-discussed-till-death-thing.
      With a correction though:
      Because we have already

      with TSomething.Create do
      begin
        //do something with the anonymous object
       Free; //<-- Explicit call
      end;
      

      …imho, is better to leave out the automatic destruction of the object.

      But with regard to aliasing, in other words, with var foo: MyVeryLongDataModuleName.CustomerDataSet do foo.Open; – well this imho is a very good thing to have but it seems that “they” had a look on it and for some reason isn’t possible. But since Nick finds this thing very annoying, let’s hope that with the new compiler we’ll have something to fix the “infamous ‘with’ resolution”.

  8. with var a: TSomething.Create do
    begin
    B := a;
    // and here it should call a.Free
    end;

    Now what happens when a is automatically freed? Be very careful to automate things. Often, they backfire.

  9. Having to scroll up and down is so annoying and I would glad to see the back of it. Having being forced by my employer to use other languages, I do feel the pain when I return to my home Delphi projects.

    The declaration block is a throwback to when Pascal was a teaching language. It also assisted compiler speed in the days of small RAM, but it did so by transferring some of the burden to the programmer. It was a good balance at the time. Hardware limits have shifted since then.

    As to laziness, if a coder is going to write rambling, undisciplined code, enforcing arbitrary restrictions like VAR declaration blocks is not going to prevent that.

    Back in the day, we produced very readable, structured code in assembler. But I had a programming lead that knew his stuff, and I learnt much from him.

    And besides, I don’t think a customer will be impressed by saying “I did this the hard way!”

    Yes, please allow the programmer to declare VAR, CONST, TYPE etc. for local BEGIN-END blocks.

    • “Having to scroll up and down is so annoying and I would glad to see the back of it. Having being forced by my employer to use other languages, I do feel the pain when I return to my home Delphi projects.”

      Yes, this is an (yet another) common complaint of programmers which program in other languages.
      Also, I agree with all the other points you make.
      And to add another one which is related to your points: Forcing us to have (local) procedures even for the smallest things (like a simple for for example) just to have an uncluttered var block leads sometimes to less readable code because sometimes our imagination fails short in finding descriptive names for the plethora of local procedures which we must write. And the above feature doesn’t exclude the old way – it just gives you the flexibility to adapt to the situation at hand.

  10. @LDS – yes, it has serious implications on the compiler. I think that is why it has never been done. I vaguely recall someone from within, at the time Borland, saying something like that.

  11. I like that variables are declared in the beginning of procedure, it makes code cleaner.

    Then again I would like to have the possibility to declare a default value for a variable. For examlpe
    procedure …
    var a: Integer=1;
    begin

    instead current:
    procedure…
    var a:Integer;
    begin
    a := 1;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s