Recent

Author Topic: Inline vars / Re: Conditional ternary operators For FreePascal?  (Read 8683 times)

440bx

  • Hero Member
  • *****
  • Posts: 6469
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #30 on: August 11, 2025, 01:13:42 pm »
I just want to make sure I get it right...

Is this thread about inline vars or is it about ternary operators or some other thing I missed ?

Thank you for shedding some light on what the actual topic is.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

LV

  • Sr. Member
  • ****
  • Posts: 427
Re: Declare variables in function body?
« Reply #31 on: August 11, 2025, 01:14:08 pm »
Now, every time I start to code in pascal, I miss this functionality. I am in the middle of a function, and realise that I need a new variable. So i move the cursor to the VAR section above, write the declaration of the var, then I go back down to the point were I was before to write the code about the new var.

This is quite more typing and it's tiring to scroll up and down whatching well in order to identify the two spots (VAR section and appropriate location in function body).

In Lazarus, there is no problem when entering an expression with a new variable. You don't need to navigate elsewhere in the code for variable declaration; press Ctrl+Shift+C and continue working in the same spot.  :)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12345
  • Debugger - SynEdit - and more
    • wiki
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #32 on: August 11, 2025, 01:15:55 pm »
I just want to make sure I get it right...

Is this thread about inline vars or is it about ternary operators or some other thing I missed ?

Thank you for shedding some light on what the actual topic is.

This is the inline vars part / it was split off the ternary op thread, where it had developed as side topic.

440bx

  • Hero Member
  • *****
  • Posts: 6469
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #33 on: August 11, 2025, 01:40:16 pm »
This is the inline vars part / it was split off the ternary op thread, where it had developed as side topic.
Great...  Thank you!

I don't like the way inline variables are implemented in C and Delphi _but_ I have to admit that being able to declare inline variables can help produce simpler and cleaner code.

It's probably the C feature I miss the most often.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

LV

  • Sr. Member
  • ****
  • Posts: 427
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #34 on: August 11, 2025, 03:14:53 pm »
Some programming languages have an alternative concept.

Basically because I half remembered the Ada syntax xD

Coding Ada: declare blocks (https://craftofcoding.wordpress.com/2018/02/16/coding-ada-declare-blocks/).

The 2008 Fortran standard introduced the notion of block which enables using local scope variables within a program or procedure (https://fortran-lang.org/learn/quickstart/variables/).

Thaddy

  • Hero Member
  • *****
  • Posts: 19129
  • Glad to be alive.
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #35 on: August 11, 2025, 03:21:09 pm »
Freepascal already supports blocks: they generally are defined by begin end. It is fundamental to the language.
The compiler knows their scope.

Note this is different from {$modeswitch cblocks} which is conceptionally more like anonymous methods, although their capture might be related
« Last Edit: August 11, 2025, 03:34:58 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

Warfley

  • Hero Member
  • *****
  • Posts: 2054
Re: Declare variables in function body?
« Reply #36 on: August 11, 2025, 04:26:07 pm »
In Lazarus, there is no problem when entering an expression with a new variable. You don't need to navigate elsewhere in the code for variable declaration; press Ctrl+Shift+C and continue working in the same spot.  :)

A well designed language should not need support of a specific editor. Thats the mistake Java made, where if not all of the members on the team use the exact same editor things get messy very fast.

I personally used vim + tmux + command line gdb for programming C and C++ for years. This was before language servers existed, and basically my way of navigating the source code was mainly grep.

When navigating the FPC compiler source code to quickly scan for something, I usually just open the gitlab page and use the gitlab search to look stuff up. No need to first clone the code and open it in lazarus, especially on a machine where I might not have it installed (or in case of my phone, can't install it).
If you need additional tooling to understand the code, it's bad language design, simple as that.

That said, if your functions are so big that scrolling to the beginning of a function is an issue, it's time to refactor the function. Thats one of the reasons I like having to declare variables at the front, it's a very good indicator whether or not your function has gotten to big
« Last Edit: August 11, 2025, 04:27:53 pm by Warfley »

gues1

  • Guest
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #37 on: August 11, 2025, 06:38:48 pm »
......  OMISSIS .......
Where there can be hundreds of lines before and after the use of the variable, making figuring out to which scope it belongs quite hard.
That said, if your functions are so big that scrolling to the beginning of a function is an issue, it's time to refactor the function. Thats one of the reasons I like having to declare variables at the front, it's a very good indicator whether or not your function has gotten to big
Are you serious when you write those things ? First you write that the code can be "HUNDREDS OF LINES" (inside a specific scope !!!) and after you speak about "function" should be refactor ?

Not keeping in mind that good code must also be well commented and comments alone could be longer than the entire logical block? It's not difficult to write code that are twenty lines lenght and one hundred lines comment lengths.

I think that some person take a position only to impose his thinking, and this is a demostration ... no logic behind this, only to say I'm doing anf thinking better than others and this is the only good way.

And choose one editor or another its only a personal flavour ... so if someone can be helped (AND NOT "MUST BE") to write something it's not  a BAD LANGUAGE DESIGN (NOTHING TO DO WITH LANGUAGE !!!!!),

Everyone knows that every logic block should be as short as possible, but it's not always POSSIBLE to have blocks that are 20 lines long.
And anyone who looked at the FPC source code would know this (with very few comments, by the way).
And this is without calling programmers who try to write the best code "id...s" 'cause they not use some instruments or others (that have nothing to do with language).

Sorry, I don't want to go under a specific people, but that is.

Stop writing that someone does the BEST and PERFECT things in the PERFECT and ONLY way and the others seem to get everything wrong.

That's all, I return to my favourite language: PASCAL.
I wish everyone the best in life. Goodbye.

Thaddy

  • Hero Member
  • *****
  • Posts: 19129
  • Glad to be alive.
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #38 on: August 11, 2025, 06:53:58 pm »
Well, Warfley has proven he CAN write such things and you absolutely not - no proof - , so Goodbye.
objects are fine constructs. You can even initialize them with constructors.

Warfley

  • Hero Member
  • *****
  • Posts: 2054
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #39 on: August 11, 2025, 07:02:11 pm »
Are you serious when you write those things ? First you write that the code can be "HUNDREDS OF LINES" (inside a specific scope !!!) and after you speak about "function" should be refactor ?
Yes, there are many projects like this, e.g. if you look into the fpcup sources, an actively maintained and rather big open source project, you find a lot of single scopes that go over hundreds of lines.

Not keeping in mind that good code must also be well commented and comments alone could be longer than the entire logical block? It's not difficult to write code that are twenty lines lenght and one hundred lines comment lengths.
No, actually to many comments is usually a bad thing, because comments tend to be outdated very quickly, as they often do not get updated when the code is updated. Someone new to the team then looks into the code, reads the comments and works according to those comments, resulting in errors because the comments do not reflect what the code does anymore. Especially very often commenting practices devolve into things like this:
Code: Pascal  [Select][+][-]
  1. { Increments i by 1 }
  2. Inc(i);
Those comments are completely useless and just blow up the code.
Good code is self documenting. Take the following code from the same file I've linked above:
Code: Pascal  [Select][+][-]
  1.             if aCompilerFound then
  2.             begin
  3.               Infoln(localinfotext+'Success: found a FPCUP(deluxe) bootstrapper with version '+aBootstrapVersion,etInfo);
  4.               break;
  5.             end
  6.             else
  7.             begin
  8.               // look for a previous (fitting) compiler if not found
  9.               s:=GetBootstrapCompilerVersionFromVersion(aBootstrapVersion);
  10.               ...
  11.             end;
You do not need that comment, do you? "If aCompilerFound then ... else ... GetBootstrapCompilerVersionFromVersion" is really self explainatory. If you have a compiler take it, if not look for another one. The comment is completely useless because the naming of the identifiers is chosen in a way that it is fully self explanatory. And the interesting thing is the code I referenced has very little comments, but all of them are kinda unecessary in this exact way.

There are a bunch of articles and as well as research papers on this that compare the effectiveness of comments and generally speaking most comments do not add additional value. Some do, and are necessary but most comments are either useless or wrong. You should only use comments when something happens that is not explainable by the code (e.g. explaining the maths behind some formulars or why a decision was taken). Anything else the code already describes.

Back when I was in Uni I have actually worked with a research project which tried to use git history to detect if code that has a comment relating to it was changed, and if the comment was changed alongside, while at the time it was not that powerful (today with LLMs it would probably work better) it showed that if i remember correctly more than 60% of comments in the evaluated open source projects where outdated to some degree

And choose one editor or another its only a personal flavour ... so if someone can be helped (AND NOT "MUST BE") to write something it's not  a BAD LANGUAGE DESIGN (NOTHING TO DO WITH LANGUAGE !!!!!),
Tools should augment the language experience, not be necessary for it. A good programming language you can write well with just notepad and a command line compiler, but you can excell using good tooling. A bad language is one that is unusable without an IDE and even worse when you choose one IDE you cannot use it in another.

Everyone knows that every logic block should be as short as possible, but it's not always POSSIBLE to have blocks that are 20 lines long.
And anyone who looked at the FPC source code would know this (with very few comments, by the way).
And this is without calling programmers who try to write the best code "id...s" 'cause they not use some instruments or others (that have nothing to do with language).
I like to take the linux kernel as an example, most core functions are just 20-40 lines long. Look at the scheduler, the process management, the memory management, the paging, etc. Nearly all of the core system follows that rule. The only exceptions are usually the drivers that require a lot of DMA which requires some nasty code. But most of us aren't writing drivers do we? Most of us just write logic and logic can usually be subdivided into different sections, which you can give meaningful names and use functions instead.
Pascal even has nested functions exactly for this reason
« Last Edit: August 11, 2025, 07:19:52 pm by Warfley »

Warfley

  • Hero Member
  • *****
  • Posts: 2054
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #40 on: August 11, 2025, 08:40:40 pm »
Everyone knows that every logic block should be as short as possible, but it's not always POSSIBLE to have blocks that are 20 lines long.
And anyone who looked at the FPC source code would know this (with very few comments, by the way).
And this is without calling programmers who try to write the best code "id...s" 'cause they not use some instruments or others (that have nothing to do with language).

Sorry, I don't want to go under a specific people, but that is.

Stop writing that someone does the BEST and PERFECT things in the PERFECT and ONLY way and the others seem to get everything wrong.

That's all, I return to my favourite language: PASCAL.
I wish everyone the best in life. Goodbye.

You know all my code I write is open source, I think in all my recent (last 5 year ish) code has not a single function with more than 100 lines of code, this includes:
1. A full RFC compliant implementation of the Websocket protocol (link)
2. A full RFC compliant implementation of the DNS Protocol and the C netdb api (Link and Link)
3. A cross plattform implementation of ANSI escapse sequenced based terminal streams (Link)
4. A full implementation of stackful co-routines (Link)

I have written very long functions before like in my AU3 IDE Project (Link) which contains a lot of very bad code, but it's 8 years old and I tried to improve and frankly have gotten much better with every single one of my projects my code quality is improving. I try with every new project I start to write better code than before
I'm not ashamed to say that I've written very bad code and I've written functions more than 100 lines in code, but I also can say that it is most of the time not necessary and if you work on your coding style you can easily write much better and readable code.
And from that experience I can say: You do not "need" to write functions this big. At least most of the time, some functions will get larger. But projects like FPCUp where functions of size >100 lines are frankly the norm in some files, definitely could be re-written.

Also thats really funny:
Quote
And anyone who looked at the FPC source code would know this (with very few comments, by the way).
Cause I did contribute to the FPC source code already in a few places, so I know the code and I know it's with some regards terrible (really good in others), e.g. it mixes german and english names for identifiers, mixes casing styles, etc. Please justify that as good practice.

Also to take an example from the fpc sources, when writing one of my merge requests (Link) I took the temp var code from the with statement, because I needed the same logic elsewhere and encapsulated it into another function, I just was able to remove like 90 lines of code from the with function into another function and it did require pretty much NO changes to the surrounding code, so putting it al into one function was absolutely unecessary.
So yeah the FPC code can be improved upon bigly, and writing these big functions is a choice not a necessaty

But I will grant that if you are in a project that uses such large functions it's a bad practice to refactor the existing code base large scale. So I try for the new code I add to write it well and use a lot of encapsulation where possible, but when working in existing functions I will of course follow the style of that function and not re-do them except it's necessary (like in the mr above)
« Last Edit: August 11, 2025, 09:14:55 pm by Warfley »

440bx

  • Hero Member
  • *****
  • Posts: 6469
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #41 on: August 11, 2025, 10:07:26 pm »
I'm not ashamed to say that I've written very bad code and I've written functions more than 100 lines in code,
I once wrote a 27,000+ lines function (close to 30 years ago.)  That's my record and, 30 years later, I have no doubt whatsoever that it is clearly superior to breaking that  code into umpteen pieces the programmer has to hunt for to see what the code does.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

linuxfan

  • Jr. Member
  • **
  • Posts: 60
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #42 on: August 12, 2025, 07:51:37 am »
@LV

Quote
Use Ctrl+Shift+C ...

This is really awesome, I've never used the shortcut this way. It can alleviate a lot what I was saying about how tiring is to scroll the source up and down to modify different sections of the source. TY.

@Martin_fr

I would not assume that inline variables are useful only when writing spaghetti code and/or the function body is too long.
For a function of only 10 lines of code, if you realize you need a new variable, you have to press arrow up ten times, and then arrow down ten times, looking at where the cursor is. These are 20 keypresses. Or you can lift the hand to grab the mouse (where is now the mouse pointer? Ah! Up there...), and click in the right place. Then move the mouse pointer away because that cursor seems an uppercase "I". And then write your declaration, and then grab the mouse again to return in the previous spot.

All this would be alleviated by Ctrl+Shift+C, TY again mr. LV.

The real problem I see is this: I think that "declare all variables before the body function" was also done to help the compiler (a one-pass compiler). Moreover, having all variables declared in a single point seems (and *can* be) a "clean way to structure the source", but is not always so. That single point of declaration can be polluted by implementation details which subtract diminish clarity instead.

Well, I don't know whether FPC is still a one-pass compiler, but anyway it seems to me that the feature of inline variables could be implemented even in a one-pass (of course I am not sure).

Take this excerpt from IniFiles.pas (which was not written by me...; it took me less than 2 minutes to find a suitable example):

Code: Pascal  [Select][+][-]
  1. function TCustomIniFile.ReadBinaryStream(const Section, Name: string; Value: TStream): Integer;
  2. Var
  3.   M : TMemoryStream;
  4.   S : String;
  5.   PB,PR : PByte;
  6.   PC : PChar;
  7.   H : String[3];
  8.   i,l2,code : Integer;
  9.  

Talking about clarity, the VAR section seems to me quite useless, especially the declaration of PB, PR, H, i, l2. Looking at function body I see that the really relevant vars are M, S and PR.
But wait! M is not even used! So the VAR block is also misleading...

I am too lazy to do it, but I am (very) convinced that the TCustomIniFile.ReadBinaryStream function, using inline variables, would have been written faster, with less effort, and more clarity. That's all.


Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12345
  • Debugger - SynEdit - and more
    • wiki
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #43 on: August 12, 2025, 12:09:41 pm »
@Martin_fr

I would not assume that inline variables are useful only when writing spaghetti code and/or the function body is too long.
For a function of only 10 lines of code, if you realize you need a new variable, you have to press arrow up ten times, and then arrow down ten times, looking at where the cursor is. These are 20 keypresses. Or you can lift the hand to grab the mouse (where is now the mouse pointer? Ah! Up there...), and click in the right place. Then move the mouse pointer away because that cursor seems an uppercase "I". And then write your declaration, and then grab the mouse again to return in the previous spot.
l
All this would be alleviated by Ctrl+Shift+C, TY again mr. LV.

Assuming the most basic editor (so you have no quicker way than 10 time the up key), then you also don't have code completion, or anything but the compiler (and yourself) that relies on the declarations.
So when you write a line of code with a new variable, you keep on writing code => you don't go to declare it just now.
Once you got your 20 to 30 lines of code (which should fit onto a screen), you do a good job and re-read what you just wrote (that is a good idea on its own). While you do that you can have the cursor in the "var" block, and add the variables.
At the same time, you will have a chance to notice, if any variable could be named better, is not required, should be split into two vars ....

If you use the Lazarus IDE (which you don't have to) then you may have added vars with ctrl-shift-C (because code completion works only once the var is declared). But then you still want to do that review.

If you use an other editor, it may still have bookmarks and other navigation features to make that less keystrokes, if you want to add vars more frequently.

And you can (within reason) reverse the process partly
Code: Pascal  [Select][+][-]
  1. start := GoGetFirst();
  2. cnt := GoGetCount();
  3. for i := start to start+cnt-1 do
  4. ...
When you add "start", you already know you need "cnt" and "i".

Mind you, I am not saying there is never a case where you would have code requiring you to go up/down more often than desirable.
But, that should be a rare-ish occurrence.

And, IMHO it does not make enough of an argument for inline vars. It just can't be the goal of any language to have tons of features added for each and every last minor case of how code occasionally may look like.
(Yes, I realize I am not the authority on how your code must look like... But, as I also said before: Every language (not just Pascal) has an impact on how code written in it will look and be structured. I have been at the point were I tried to write Pascal in the style of other languages, and that just was bad in every way, Pascal did not support those styles. In a sense, even Delphi now is a different language. I can't judge what influences your style, but give it some thought, please)

And as I pointed out, inline-vars are not free of cost (not speaking of the maintenance of the compiler sources / but of the negative effects it can have on the user code). And those effects are affecting everyone. There is no opt out, everyone will be faced with reading code of others.

E.g. my earlier example:
Code: Pascal  [Select][+][-]
  1. var foo: integer; // global / but could be class field / even in a diff unit
  2.   // in some cases (not below) it could even be a function
  3. {...}
  4. procedure bar;
  5. begin
  6. {...}
  7.   foo := CurrentFoo();
  8. {...}
  9.   if ... then begin
  10.     var foo: integer;
  11. {...}
  12.      DoWork(foo); // ups, you do not work on CurrentFoo
  13.   end;
  14.   if ... then begin
  15. {...}
  16.      DoWork(foo); // ups, you do not work on the local var
  17.   end;
  18. end;
  19.  

Especially if one doesn't use Lazarus with code navigation, then one can't easily find that declaration. So then one would be screwed.
(I don't have Delphi, I can't verify the example, but I am sure something like this can happen, even if it needs a bit different setup)



So then, the cost must be compared
- New source of errors
versus
- Bit more work to declare the vars
  (if you use an editor that does not help you, and depending on how you organize your code)

Mind that outside the IDE, you could still have editors that help you
- bookmarks are common and can help navigate between code and var block
- user definable macros exist in several editors, they could do the navigation, or even more



Quote
The real problem I see is this: I think that "declare all variables before the body function" was also done to help the compiler (a one-pass compiler). Moreover, having all variables declared in a single point seems (and *can* be) a "clean way to structure the source", but is not always so. That single point of declaration can be polluted by implementation details which subtract diminish clarity instead.
That it may also help the compiler is not a reason against other benefits it has.
Besides, "inline" can be done as a single pass, but then you need to dynamically change the allocation of the stack frame.

Quote
Take this excerpt from IniFiles.pas (which was not written by me...; it took me less than 2 minutes to find a suitable example):

Code: Pascal  [Select][+][-]
  1. function TCustomIniFile.ReadBinaryStream(const Section, Name: string; Value: TStream): Integer;
  2. Var
  3.   M : TMemoryStream;
  4.   S : String;
  5.   PB,PR : PByte;
  6.   PC : PChar;
  7.   H : String[3];
  8.   i,l2,code : Integer;
  9.  

Talking about clarity, the VAR section seems to me quite useless, especially the declaration of PB, PR, H, i, l2. Looking at function body I see that the really relevant vars are M, S and PR.
But wait! M is not even used! So the VAR block is also misleading...

I am too lazy to do it, but I am (very) convinced that the TCustomIniFile.ReadBinaryStream function, using inline variables, would have been written faster, with less effort, and more clarity. That's all.

Well, you can declare a variable inline, and then not use it. So for that it makes no difference.

The real problem I see here, is the choice of names for the variables. If you have that many (or if your code is more than a few lines) then  they should have more meaningful names. That helps making the code more readable.
And of course, meaningful names can be given with or without inline vars.

But, with pre-declared vars, there may be a nice workflow, helping with meaningful vars. Well at least there is a workflow that I like very much.
- While writing code (and things still change a lot), I use short meaningless names (I may end up with completely unreadable i,j,k,l,m,n,o,p vars).
- When I have enough code (not necessarily all done), I use syncre-edit (several editors have that / but search replace also does the job). And I rename the variables.

So the one major difference is:
- Pre-declared gives me a nice list in one place, which I can (have the option to) use to rename them into something more meaningful.
- inline means I have to search for each var I introduced. Much more work, and higher chance to miss one.

And well, sometimes I forget or am lazy. But inline vars wouldn't change that.
« Last Edit: August 12, 2025, 12:11:18 pm by Martin_fr »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12345
  • Debugger - SynEdit - and more
    • wiki
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #44 on: August 12, 2025, 12:50:24 pm »
One more reason, not to inline.
Even (or maybe especially) if you have the most basic editor (on tools to help with anything).

Then depending on workflow, style and .... it may save between a little and a moderate amount of keystrokes to declare the var inline.

But, that is only when you first write the code. To decide your total cost (plus/minus) you need to consider the work for maintaining that code later. Maintaining in the same basic editor, with the same lack of tools.

So you have inline
Code: Pascal  [Select][+][-]
  1. procedure xyz,
  2. begin
  3.   {...}
  4.   SetFoo(1); // some comment about foo
  5.   {...}
  6.   var foo: integer := 0;
  7.   {...}
  8.   if bar then foo := 1;
  9.   {...}
  10.   foo := GetFoo();
  11.  

Now GetFoo changes to int64 or cardinal. You need to change the code.

Your editor wont even parse the compiler error, to help you to the error line... But if it does, once at the error line, you still need to get to where foo is declared as integer.
How to you get there? You have no code navigation. Simple search requires several steps (backwards, and you may step to far, to the comment). And searching from the start of the procedure requires several steps too.

Finding the begin of the procedure is likely much easier.
« Last Edit: August 12, 2025, 12:53:06 pm by Martin_fr »

 

TinyPortal © 2005-2018