Recent

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

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 302
  • I use FPC [main] 💪🐯💪
This isn't exactly related to the topic, but since the topic of InlineVar has been brought up, I would like to speak up in defense of InlineVars

In addition to the obvious convenience of using InlineVars in loop counters, there is another less obvious advantage when working with managed types, such as strings

Here are two code options, one without InlineVar and one with InlineVar:
1.
Code: Pascal  [Select][+][-]
  1. program app;
  2. {$iochecks off}
  3.  
  4. uses SysUtils;
  5.  
  6. procedure test;
  7. var
  8.   s: string;
  9. begin
  10.   WriteLn(1);
  11.   if Random>0.5 then
  12.   begin
  13.     s := 'kek' + Random.ToString;
  14.     WriteLn(s);
  15.   end;
  16.   WriteLn(2);
  17.   // Implicit call to string s finalization here
  18. end;
  19.  
  20. begin
  21.   test;
  22. end.

2.
Code: Pascal  [Select][+][-]
  1. program app;
  2. {$iochecks off}
  3.  
  4. uses SysUtils;
  5.  
  6. procedure test;
  7. begin
  8.   WriteLn(1);
  9.   if Random>0.5 then
  10.   begin
  11.     var s := 'kek' + Random.ToString;
  12.     WriteLn(s);
  13.     // Implicit call to string s finalization here
  14.   end;
  15.   WriteLn(2);
  16. end;
  17.  
  18. begin
  19.   test;
  20. end.

In the first option, without InlineVar, you will always have an implicit finalization of the string variable at the end of the procedure

In the second option, with InlineVar, string finalization will only be called when it is used; if it is not used, then there will be no finalization call, which is very convenient and provides better performance

In FPC, there are currently several ways to work around this:
1. Wrap such string operations in a procedure (possibly even a nested one)
2. Use the {$IMPLICITEXCEPTIONS} directive and finalize such variables yourself

InlineVar's seem more convenient in these cases, eliminating unnecessary manual work, IMHO
I may seem rude - please don't take it personally

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11824
  • Debugger - SynEdit - and more
    • wiki
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #1 on: August 09, 2025, 10:59:16 am »
In addition to the obvious convenience of using InlineVars in loop counters, there is another less obvious advantage when working with managed types, such as strings
Quote
In the first option, without InlineVar, you will always have an implicit finalization of the string variable at the end of the procedure

In the second option, with InlineVar, string finalization will only be called when it is used; if it is not used, then there will be no finalization call, which is very convenient and provides better performance

That is an argument for a better optimizer. DFA should be able to detect the life time of a variable, and optimize the rest of the code accordingly.

Burden the user with that task is just not right.

Also the scoped finalize only makes sense, if there is no other finalize call into which it can be added (saving the cost of 2 calls).
I.e. if there is another managed var, and its scope is a superset of the first, then just finalize the first, in the outer call.
(or if there is a user specified "finalize" statement)

I wouldn't want to have to analyse my code each time I change a variable, if all inline declarations are at optimal positions.

And since the optimizer would have to do that job, with or without inline vars => this is not an argument for inline vars, not at all.

Quote
InlineVar's seem more convenient in these cases, eliminating unnecessary manual work, IMHO

As I see it, they massively add manual work. As they all (in case of more than one var) need to be synced with each other.

And, if the optimizer does that, then it should do it without inline vars too.
« Last Edit: August 09, 2025, 11:04:44 am by Martin_fr »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11824
  • Debugger - SynEdit - and more
    • wiki

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 302
  • I use FPC [main] 💪🐯💪
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #3 on: August 09, 2025, 11:13:33 am »
Hmm... now I understand, now I agree with you regarding managed types 👍
I may seem rude - please don't take it personally

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12536
  • FPC developer.
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #4 on: August 09, 2025, 12:07:17 pm »
In the first option, without InlineVar, you will always have an implicit finalization of the string variable at the end of the procedure
In the second option, with InlineVar, string finalization will only be called when it is used; if it is not used, then there will be no finalization call, which is very convenient and provides better performance

For a basic compiler. But if you set that kind of behaviour (and the guarantee that inlinevars behave that way) in stone, you actually hamper future optimisation options in the compiler

Ah, Martin already spotted that. I agree.



« Last Edit: August 09, 2025, 02:46:29 pm by marcov »

my_only_lonely

  • New Member
  • *
  • Posts: 15
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #5 on: August 09, 2025, 02:39:13 pm »
I totally agree with you.

C89 also forced variable declaration must before any code. But they also change it in the new C standard.
Stick to the last century style, and say it is a Pascal style, does not really make any sense, since almost all modern language has this. It is the choice made by almost all modern languages. This is not Pascal style, more like a legacy burdern.
You can also say compiler should be smart enough to detect such cases. Similar discussion has been talk for ages, last time it was the same argument. But I'm not seeing anyone willing to implement this. At least Delphi has changed something.

gues1

  • Guest
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #6 on: August 09, 2025, 02:49:00 pm »
Inline vars were not created to optimize the code (performance for example) ... think that:

- I declare one normal local variable of type string, used in 5 different blocks: one initialization, one finalizaton;

- the same using inline vars: may be five initializations and five finalizations.

Not optimal performance ...

They were created specially to give a new instruments to isolate potential issue. And with this perspective should be used.



marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12536
  • FPC developer.
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #7 on: August 09, 2025, 03:37:46 pm »
They were created specially to give a new instruments to isolate potential issue. And with this perspective should be used.

I'm not sure about that. Can you elaborate ? 

IMHO it is purely a visual thing for the programmer. Opinions on that can vary. But there are few hard truths about the syntax. Implementation details or warnings can be solved with a better compiler (liveliness analysis and propagation).  Currently Pascal has no concept of programmer assisting in propagates constness like C++ (and I do wonder how much it is needed in the first place)

Nor should it be confused with type inference. That is a different subject, and the people in favour or not might be different.
« Last Edit: August 09, 2025, 03:46:52 pm by marcov »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11824
  • Debugger - SynEdit - and more
    • wiki
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #8 on: August 09, 2025, 04:07:20 pm »
Unfortunately I can't test what is allowed in Delphi and what is not.

But the following works in fpc.
Code: Pascal  [Select][+][-]
  1. procedure Foo;
  2. var i: integer;
  3.   procedure Nested;
  4.   var i: integer;
  5.   begin
  6.     {...}
  7.     writeln(i);
  8.   end;
  9. begin
  10.   {...}
  11. end;


Now, if that also works in Delphi, then I would expect that the following works too
Code: Pascal  [Select][+][-]
  1. procedure Foo;
  2. var i: integer;
  3.   procedure Nested;
  4.   begin
  5.     {...}
  6.     var i := 123;
  7.     {...}
  8.     writeln(i);
  9.   end;
  10. begin
  11.   {...}
  12. end;


And suddenly it's far less noticeable, that the writeln does not refer to the outer Foo's var "i".
IMHO, that really makes increases the chances of an error in that case....

And for a maybe more likely example => the same should be happening if it wasn't a nested proc, but if there was a global var (or function, ...).

Or in any other case where an identifier can be hidden by one other of the same name.

So there are plenty of cases.

And code grows. If all procedures were really really small, then the scoping of an inline var wouldn't make any change at all. But if procs are bigger, then inline vars can hide very very well.



And please don't reply "But that is bad code" / "that abuses the feature" / "shouldn't be used like that" / ....

Because, usually inline vars are advertised to help, if code without them would be more error prone => but if the above is just "bad code" / "abuse" ...

Well, then how come that any code that supposedly needs to be "improved" with inline vars, that such code is not equally "bad code" / "abuse" ...?

But, if it comes down, to using the tools correctly (with or without inline vars), then what improvement do they add?

Say the "for loop" example? But if it is just that, does that really make up for the down sides?

Thaddy

  • Hero Member
  • *****
  • Posts: 18363
  • Here stood a man who saw the Elbe and jumped it.
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #9 on: August 09, 2025, 05:06:59 pm »
If the inline var is only for an index, just make index a reserved word (which it already is for properties) and make it implied:
Code: Pascal  [Select][+][-]
  1. begin
  2. { index is a reserved word that implies the variable is only used as an index,
  3.   no need to declare it because of that. }
  4.   for index := 0 to 11 do; // volume, custom Marshall
  5. end.
  6.  
Problem solved. In a more elegant way than Delphi.
I expressed that opinion before...
This can even be done for:
Code: Pascal  [Select][+][-]
  1. for index do
  2.   for index do;//
because the context can be captured.(because blocks are already captured)
That would be way,way better than Delphi.....
« Last Edit: August 09, 2025, 05:27:53 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Thaddy

  • Hero Member
  • *****
  • Posts: 18363
  • Here stood a man who saw the Elbe and jumped it.
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #10 on: August 09, 2025, 08:25:13 pm »
I might add this is already somewhat possible in trunk by means of a factory and an anonymous function.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

BeniBela

  • Hero Member
  • *****
  • Posts: 947
    • homepage
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #11 on: August 09, 2025, 11:06:26 pm »
If FreePascal lacks Delphi syntax,  it does not have a
Code: [Select]
{$mode delphi} but a
Code: [Select]
{$mode delphi-like}

and then you cannot use libraries

For example, I found an XML parser for Delphi: https://blog.grijjy.com/2020/10/07/an-xml-dom-with-just-8-bytes-per-node/

which has the lowest memory usage of all xml parsers.
But it uses inline variables and the author said he will continue to use them because it doesn't matter to him that FreePascal does not support that.

without inline variables in fpc, I would have to program my own XML parser
 



Say the "for loop" example? But if it is just that, does that really make up for the down sides?

yes, it makes up for all down sides

especially in Pascal when after the loop the value of the index variable is undefined

one could introduce a personal programming style, each variable is initialized asap after the declaration and each variable name is only once used in the program to reduce errors. but that still doesn't help with the for loop because the variable still becomes uninitialized




Warfley

  • Hero Member
  • *****
  • Posts: 2021
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #12 on: August 10, 2025, 01:17:16 am »
What makes you think that inline variables enforce lifetime scoping? Those are two different concepts, and if you would implement inline variables naively, like I did some time ago in a quick and dirty patch, it would still not implement lifetime scoping.

On the other hand I made a merge request that enables lifetime scoping some time ago without inline variables but using a different construct, scoped with: gitlab.com/freepascal.org/fpc/source/-/merge_requests/860

Basically if you need to enforce the lifetime you can do it with a with block:
Code: Pascal  [Select][+][-]
  1. with const s = GetBigString() do
  2. begin
  3.  
  4. end; // String in s will be finalized as soon as the with block is over

The difference to an inline variable is the following:
1. It's not a variable, it's a single object that is assigned once where the lifetime is specifically that of the with block (thats why the const keyword is used)
2. It is directly coupled with a block, unlike inline variables that can occur anywhere, this can only be declared for a single with block, so you know exactly what is available where (meanwhile inline variables can go anywhere, in the middle of the block)
3. It works with the plain with statement as well:
Code: Pascal  [Select][+][-]
  1. with GetManagedRecord do
  2.   // Use managed record
  3. // After with block it will be finalized
Which was actually the original idea, adding a named identifier for it just came later on.

Note the idea is not new, python for example uses the exact same concept:
Code: Pascal  [Select][+][-]
  1. with open(filename, "r") as fl:
  2.   # Use fl
  3. # after with fl will be freed
Exactly for the same reason. Because python can be either garbage collected or reference counted depending on the interpreter settings, you can't know when an object will be freed. With was introduced in python to circumvent this and give the programmer the ability to specifically say when a finalizer must be called.
« Last Edit: August 10, 2025, 01:19:00 am by Warfley »

jamie

  • Hero Member
  • *****
  • Posts: 7317
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #13 on: August 10, 2025, 12:14:09 pm »
Oh that's really neat will it support multiple variables of different types in that construct?
The only true wisdom is knowing you know nothing

Warfley

  • Hero Member
  • *****
  • Posts: 2021
Re: Inline vars / Re: Conditional ternary operators For FreePascal?
« Reply #14 on: August 10, 2025, 12:25:24 pm »
Yeah you can chain it like normal with statements:
Code: Pascal  [Select][+][-]
  1. with const a = openfile(infile, fmopenread),
  2.      const b = openfile(outfile, fmcreate) do
  3.   while not a.eof do
  4.     b.writebyte(a.readbyte);
Basically the usage of advanced records for file operations, which automatically close the file when they are finalized was exactly the idea why I built it, to allow something like that
« Last Edit: August 10, 2025, 12:30:27 pm by Warfley »

 

TinyPortal © 2005-2018