Recent

Author Topic: Modern For Loop question  (Read 8281 times)

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Modern For Loop question
« on: January 25, 2021, 10:47:05 pm »
Shouldnt this compile?

I get "illegal assignement" at line 14 (FPC 3.3.1)
Ok, I am aware, I did something wrong probably, but I dont know, how to do it right.

Code: Pascal  [Select][+][-]
  1. procedure MultiThread(FromIndex, ToIndex: Integer; Proc: DoProcProcedure; ThreadCount: Integer = 8);
  2. var
  3.   Workers: array of TMyWorkerThread;
  4.   I: integer;
  5.   t: TMyWorkerThread;
  6.   begin
  7.   SetLength(Workers, ThreadCount);
  8.   CurrentIndex := FromIndex;
  9.   MaxIndex := ToIndex;
  10.  // for I := 0 to ThreadCount - 1 do
  11.  //      Workers[I] := TMyWorkerThread.Create(Proc);
  12.  
  13.  for t in workers do
  14.        t := t.Create(Proc);   // <-- Error: illegal assignement
  15.  
  16.  while CurrentIndex < MaxIndex do
  17.     sleep(100);
  18.  
  19. end;    
  20.  
« Last Edit: January 25, 2021, 10:51:50 pm by Peter H »

Kays

  • Hero Member
  • *****
  • Posts: 569
  • Whasup!?
    • KaiBurghardt.de
Re: Modern For Loop question
« Reply #1 on: January 25, 2021, 11:00:16 pm »
[…]
Ok, I am aware, I did something wrong probably, but I dont know, how to do it right. […]
The iterator variable is immutable, thus it cannot appear on the LHS of an assignment.
The code above you commented out looks alright though. Slight improvement: Use high for the upper limit.
Yours Sincerely
Kai Burghardt

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Re: Modern For Loop question
« Reply #2 on: January 25, 2021, 11:05:43 pm »
Yes, the commented code is alright.
I wanted to write this more modern and elegant.

My thought was: t is not an iterator, it is what an immutable hidden iterator points to, therefore I can modify it.
Possibly I understand this wrong.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Modern For Loop question
« Reply #3 on: January 25, 2021, 11:06:41 pm »
for x in somearray do

is syntax sugar, and you have to regard the loop variable x as read-only from the programmer's point of view.

As Kays writes, the classic syntax gives you more flexibility, though it is slightly more verbose.

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Re: Modern For Loop question
« Reply #4 on: January 25, 2021, 11:16:49 pm »
for x in somearray do

is syntax sugar, and you have to regard the loop variable x as read-only from the programmer's point of view.

As Kays writes, the classic syntax gives you more flexibility, though it is slightly more verbose.

Some say, it is sugar, others say, it is less fat, less writing means better readable and better maintenance and less errors.  ;D
It shouldnt be necessary to tell something to the compiler, when it already knows it.
This is nothing to discuss.
BTW, I have your book, it is excellent, no offence please.
« Last Edit: January 26, 2021, 12:22:35 am by Peter H »

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Re: Modern For Loop question
« Reply #5 on: January 25, 2021, 11:27:21 pm »
I got now this, it compiles, but doesnt work at runtime:

Code: Pascal  [Select][+][-]
  1. procedure MultiThread(FromIndex, ToIndex: Integer; Proc: DoProcProcedure; ThreadCount: Integer = 8);
  2. var
  3.   Workers: array of TMyWorkerThread;
  4.   I: integer;
  5.   t: ^TMyWorkerThread;
  6.   begin
  7.   SetLength(Workers, ThreadCount);
  8.   CurrentIndex := FromIndex;
  9.   MaxIndex := ToIndex;
  10.  // for I := 0 to ThreadCount - 1 do
  11.  //      Workers[I] := TMyWorkerThread.Create(Proc);
  12.  
  13.  for t^ in workers do
  14.       t^ := t^.Create(Proc);  
  15.  
  16.  while CurrentIndex < MaxIndex do
  17.     sleep(100);
  18.  
  19. end;
  20.  
« Last Edit: January 25, 2021, 11:31:04 pm by Peter H »

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Re: Modern For Loop question
« Reply #6 on: January 26, 2021, 12:15:37 am »
This compiles AND works:


Edit: If i initialyze "t" to Nil, it throws an exception. It doesnt work.

Code: Pascal  [Select][+][-]
  1. procedure MultiThread(FromIndex, ToIndex: Integer; Proc: DoProcProcedure; ThreadCount: Integer = 8);
  2. var
  3.   Workers: array of TMyWorkerThread;
  4.   I: integer;
  5.   t: ^TMyWorkerThread = Nil;
  6.   begin
  7.   SetLength(Workers, ThreadCount);
  8.   CurrentIndex := FromIndex;
  9.   MaxIndex := ToIndex;
  10.  // for I := 0 to ThreadCount - 1 do
  11.  //      Workers[I] := TMyWorkerThread.Create(Proc);
  12.  
  13.  for t^ in workers do
  14.       t^ := TMyWorkerThread.Create(Proc);
  15.  
  16.  while CurrentIndex < MaxIndex do
  17.     sleep(100);
  18.  
  19. end;
  20.  
  21.  
« Last Edit: January 26, 2021, 01:25:37 am by Peter H »

Kays

  • Hero Member
  • *****
  • Posts: 569
  • Whasup!?
    • KaiBurghardt.de
Re: Modern For Loop question
« Reply #7 on: January 26, 2021, 12:26:16 am »
[…] I wanted to write this more modern and elegant. […]
You cannot use for … in … do for that. The problem is the loop body receives a copy of the array member’s value. In the loop body, the collection (the array) you specified between in … do, is not touched again.

Only by using a for … to … do loop and writing myArray[myCountingVariable] you actually have access to the array and can manipulate it, its contents.

This compiles AND works:
Yeah, OK, handling pointers to pointers. That’ll just circumvent the immutability requirement (as far as the compiler can detect it). What’s the gain, the advantage though? Frankly, it’s nice that it works, but I’d probably opt for the more intuitive/readable solution.
Yours Sincerely
Kai Burghardt

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Re: Modern For Loop question
« Reply #8 on: January 26, 2021, 01:18:17 am »
Yes, you are right.
If I initialize t like this:  var  t: ^TMyWorkerThread = Nil ,then I get an exception with both compiling examples.
It was an accident, that example no. 3 did work, now it throws an exception.
None of all these examples work.
« Last Edit: January 26, 2021, 01:30:29 am by Peter H »

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Modern For Loop question
« Reply #9 on: January 26, 2021, 09:17:44 am »
Don't abuse the forin loop for something that it isn't intended for. Consider the loop variable as immutable. Period. Even if you should find a way that works for you now there is no guarantee that this will work in future versions or with improved optimizations.

Peter H

  • Sr. Member
  • ****
  • Posts: 272
Re: Modern For Loop question
« Reply #10 on: January 26, 2021, 09:26:00 am »
Now I did not want to abuse it, I wanted to use it.
But obviously I had a misunderstanding about it.
I think I must have some educational reading how to use it. What would you recommend?
I have 4 paid books about lazarus/freepascal, but none explains it in depth, e.g. "Getting started with Lazarus and Free Pascal" by "Menkaura Abiola-Ellison" has only a very short example how to process lists.
« Last Edit: January 26, 2021, 10:27:44 am by Peter H »

egsuh

  • Hero Member
  • *****
  • Posts: 1273
Re: Modern For Loop question
« Reply #11 on: January 26, 2021, 09:37:51 am »
It seems that for...in AnArray returns the constant (as Kays already told), not variable, while AnArray[Index] is actually a pointer of a variable, which you can store values.

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Modern For Loop question
« Reply #12 on: January 26, 2021, 12:40:28 pm »
There were discussions about it before. I think the for..in construct is very useful to avoid boundary-mistakes. But because its not usable in the case you showed, and thats a frequent case, the usecases are too rare to consequently use it. And I don't like changing the complete loop structure, just because something in the inner of the loop changed.

An assignable iterator should be allowed, imo. I understand, that the problem is the iterator implementation and not the loop implementation itself, that could be changed.

And a construct like the below would be very helpful for save programming (Feature request ;-)

Code: Pascal  [Select][+][-]
  1. for ii with someElement in SomeArray
  2. do someElement.index:= ii;

ASBzone

  • Hero Member
  • *****
  • Posts: 678
  • Automation leads to relaxation...
    • Free Console Utilities for Windows (and a few for Linux) from BrainWaveCC
Re: Modern For Loop question
« Reply #13 on: January 26, 2021, 03:51:13 pm »
There were discussions about it before. I think the for..in construct is very useful to avoid boundary-mistakes. But because its not usable in the case you showed, and thats a frequent case, the usecases are too rare to consequently use it. And I don't like changing the complete loop structure, just because something in the inner of the loop changed.

An assignable iterator should be allowed, imo. I understand, that the problem is the iterator implementation and not the loop implementation itself, that could be changed.

And a construct like the below would be very helpful for save programming (Feature request ;-)

Code: Pascal  [Select][+][-]
  1. for ii with someElement in SomeArray
  2. do someElement.index:= ii;

Can you provide a practical example of what you are sort of requesting here?

I'm not seeing or understanding the desired use cases.
-ASB: https://www.BrainWaveCC.com/

Lazarus v2.2.7-ada7a90186 / FPC v3.2.3-706-gaadb53e72c
(Windows 64-bit install w/Win32 and Linux/Arm cross-compiles via FpcUpDeluxe on both instances)

My Systems: Windows 10/11 Pro x64 (Current)

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Modern For Loop question
« Reply #14 on: January 26, 2021, 04:32:32 pm »
Loop variables in a for loop are by design not assignable.
This is Pascal after all.

Bart

 

TinyPortal © 2005-2018