Recent

Author Topic: Why with allows assignment  (Read 43539 times)

Okoba

  • Hero Member
  • *****
  • Posts: 616
Why with allows assignment
« on: January 02, 2025, 09:12:00 am »
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. type
  4.   TTest = record
  5.     V: Integer;
  6.   end;
  7.  
  8. var
  9.   X: TTest;
  10.  
  11.   function Test: TTest;
  12.   begin
  13.     Result := X;
  14.   end;
  15.  
  16. var
  17.   T: TTest;
  18. begin
  19.   with Test do
  20.     V := 1; //No Error
  21.   Test.V := 1; //Error: Argument cannot be assigned to
  22. end.                

Why the first test raise no error like the second one?

And on the same topic, is there a way in Pascal that I can return a record by the reference so any change to the result, changes the source?
For example changing V changes the original X.
I know I can return the pointer, but is there any other way?
« Last Edit: January 02, 2025, 09:28:48 am by Okoba »

egsuh

  • Hero Member
  • *****
  • Posts: 1563
Re: Why with allows assignment
« Reply #1 on: January 02, 2025, 09:30:04 am »
I think  with with Test, function Test is evaluated which means an address (and memory space) is allocated, while in Test.V, Test itself is nil so that it is error.

cdbc

  • Hero Member
  • *****
  • Posts: 1967
    • http://www.cdbc.dk
Re: Why with allows assignment
« Reply #2 on: January 02, 2025, 09:38:12 am »
Hi
Quote
And on the same topic, is there a way in Pascal that I can return a record by the reference so any change to the result, changes the source?
For example changing V changes the original X.
I know I can return the pointer, but is there any other way?
Records are copied by value, so no, that's why we use pointers or 'var' parameters, which are basically pointers to the value...
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

alpine

  • Hero Member
  • *****
  • Posts: 1374
Re: Why with allows assignment
« Reply #3 on: January 02, 2025, 09:39:48 am »
The function result is a temporary and the assignment is of no effect. It is debatable whether it is an error, probably there is no such check on with.
See: https://forum.lazarus.freepascal.org/index.php/topic,60561.0.html
« Last Edit: January 02, 2025, 09:44:13 am by alpine »
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zvoni

  • Hero Member
  • *****
  • Posts: 2914
Re: Why with allows assignment
« Reply #4 on: January 02, 2025, 09:52:11 am »
https://forum.lazarus.freepascal.org/index.php/topic,39961.msg275471.html#msg275471
Quote
No. The left side of an ":=" statement must have a (non temporary?) memory address and be writable. A function result doesn't.

For the part with "With Test": I'm with egsuh on this.
"With" starts a new scope, and in this case (probably?) evaluates the "Test"-Function and returns the Result, getting an Address in Memory.
The moment the code leaves the "With"-scope that memory is discarded
« Last Edit: January 02, 2025, 09:54:40 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Okoba

  • Hero Member
  • *****
  • Posts: 616
Re: Why with allows assignment
« Reply #5 on: January 02, 2025, 09:54:14 am »
Hi
Quote
And on the same topic, is there a way in Pascal that I can return a record by the reference so any change to the result, changes the source?
For example changing V changes the original X.
I know I can return the pointer, but is there any other way?
Records are copied by value, so no, that's why we use pointers or 'var' parameters, which are basically pointers to the value...
Regards Benny

So you can not make something like String with records?

Okoba

  • Hero Member
  • *****
  • Posts: 616
Re: Why with allows assignment
« Reply #6 on: January 02, 2025, 09:55:04 am »
https://forum.lazarus.freepascal.org/index.php/topic,39961.msg275471.html#msg275471
Quote
No. The left side of an ":=" statement must have a (non temporary?) memory address and be writable. A function result doesn't.

For the part with "With Test": I'm with egsuh on this.
"With" starts a new scope, and in this case (probably?) evaluates the "Test"-Function and returns the Result, getting an Address in Memory.
The moment the code leaves the "With"-scope that memory is discarded

Then why the first test using with returns no error?!

egsuh

  • Hero Member
  • *****
  • Posts: 1563
Re: Why with allows assignment
« Reply #7 on: January 02, 2025, 10:00:49 am »
Quote
Then why the first test using with returns no error?!

At the moment of assignment, there exists memory space. Anyway I think you cannot access the value even within "with" scope because there are no way to know the address.

Zvoni

  • Hero Member
  • *****
  • Posts: 2914
Re: Why with allows assignment
« Reply #8 on: January 02, 2025, 10:01:08 am »
https://forum.lazarus.freepascal.org/index.php/topic,39961.msg275471.html#msg275471
Quote
No. The left side of an ":=" statement must have a (non temporary?) memory address and be writable. A function result doesn't.

For the part with "With Test": I'm with egsuh on this.
"With" starts a new scope, and in this case (probably?) evaluates the "Test"-Function and returns the Result, getting an Address in Memory.
The moment the code leaves the "With"-scope that memory is discarded
Then why the first test using with returns no error?!
Because it has a valid and writable address in memory, allowing you to access "V" and write to it.

It's the same as
Code: Pascal  [Select][+][-]
  1. With TSomeClass.Create Do
  2.   Begin
  3.     SomeInteger:=42;    //Assign 42 to Field/Property "SomeInteger"
  4.     DoSomething; //Execute Method "DoSomething" of TSomeClass
  5.   End;
This works because the whole "With"-Block represents a valid Address in memory, for the lifetime of the "With"-Block
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Okoba

  • Hero Member
  • *****
  • Posts: 616
Re: Why with allows assignment
« Reply #9 on: January 02, 2025, 10:09:18 am »
I think that "I can not set the result of function directly" and "with gives you direct access to that variant". But what I think you are saying is that `with` is copying the result of function so it can allow setting the value of that temp silently. It seems wrong from the point of a reader like me. I get the technicality of it, but it leads to dangerous results.

Zvoni

  • Hero Member
  • *****
  • Posts: 2914
Re: Why with allows assignment
« Reply #10 on: January 02, 2025, 10:18:52 am »
I think that "I can not set the result of function directly" and "with gives you direct access to that variant". But what I think you are saying is that `with` is copying the result of function so it can allow setting the value of that temp silently. It seems wrong from the point of a reader like me. I get the technicality of it, but it leads to dangerous results.
That's exactly the reason why i have never used "with" in my life.
It confuses the hell out of me
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

cdbc

  • Hero Member
  • *****
  • Posts: 1967
    • http://www.cdbc.dk
Re: Why with allows assignment
« Reply #11 on: January 02, 2025, 10:24:35 am »
Hi
Well, yes the 'with' construct can be a bit /dangerous/ for/to the unwary...
Basically what 'with' does is *keep* the temporary result /alive/ long enough, for you to use it and then discards it :(
Quote
So you can not make something like String with records?
Well, yes and no - it depends on what you're doing...  %)
If you need to *have* the content in the record, then use 'ShortString' or for longer than 256 char strings use e.g.: 'array[0..1023] of char;' Those strings will stay in the record even when copied or written to disk.
Otoh, nothing stops you from using ansistrings or widestrings in records, just as long as you're clear about the fact, that it's *only* a pointer to the actual /string-content/ placed somewhere else. Write such a record to file and you'll see, only the pointer-value of the string is written, *not* the actual content!
HTH
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 3.6 up until Jan 2024 from then on it's both above &: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 4.99

440bx

  • Hero Member
  • *****
  • Posts: 5080
Re: Why with allows assignment
« Reply #12 on: January 02, 2025, 10:53:14 am »
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. { removed }
  4.  
  5. var
  6.   T: TTest;
  7. begin
  8.   with Test do
  9.     V := 1; //No Error
  10.   Test.V := 1; //Error: Argument cannot be assigned to
  11. end.                

Why the first test raise no error like the second one?
I believe you found a compiler bug.  "with Test do V := 1;" should be _exactly_ the same as "Test.V := 1;".  "with" is basically a way to abbreviate, it's not supposed to have any side effect.  IMO and formally, that is a bug.

Let's see what the FPC developers say.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

alpine

  • Hero Member
  • *****
  • Posts: 1374
Re: Why with allows assignment
« Reply #13 on: January 02, 2025, 11:08:04 am »
Quote
Let's see what the FPC developers say.
There are posts from PascalDragon in the link I have provided. It is the same topic.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

DragoRosso

  • Guest
Re: Why with allows assignment
« Reply #14 on: January 02, 2025, 11:22:59 am »
In Delphi, both the assignment within the WITH and the direct assignment are indicated as errors.
I believe (but I am the last one to give credence to) that a similar situation should be handled and the error should be reported to the developer.
That assignment is an error, and therefore it should be reported, even if it does not produce any effect, and that is precisely the point: the developer writing that code expects it to be executed (ok, he wrote a stupid thing) and the fact that it is not executed (or that it cannot be executed) MUST be reported by the compiler.
« Last Edit: January 02, 2025, 11:25:42 am by DragoRosso »

 

TinyPortal © 2005-2018