Lazarus

Free Pascal => General => Topic started by: circular on August 11, 2020, 03:46:43 pm

Title: while loop with code before comparison
Post by: circular on August 11, 2020, 03:46:43 pm
Suppose I want to display random numbers while they are less than some number. Such program can be written as:
Code: Pascal  [Select][+][-]
  1. var a: integer;
  2. begin
  3.   writeln('here are random percentages <= 75%');
  4.   randomize;
  5.   while true do
  6.   begin
  7.     a := random(101);
  8.     if a > 75 then break;
  9.     writeln(a, '%');
  10.   end;
  11. end.

This works, but I don't like the misleading "while true". The real condition is a <= 75. In C the solution to this is to used an assignment inside the condition, but I don't like it either.

So how about a language construct that would express that. For example:
Code: Pascal  [Select][+][-]
  1. var a: integer;
  2. begin
  3.   writeln('here are random percentages <= 75%');
  4.   randomize;
  5.   for a := random(101)
  6.   while a <= 75 do
  7.     writeln(a, '%');
  8. end.

This would work as well with blocks of code:
Code: Pascal  [Select][+][-]
  1. var a, min, max: integer;
  2. begin
  3.   writeln('here are random percentages <= 75%');
  4.   randomize;
  5.   for
  6.   begin
  7.     min := 0;
  8.     max := 100;
  9.     a := random(max-min+1) + min;
  10.   end
  11.   while a <= 75 do
  12.   begin
  13.     writeln('here is one such percentage:');
  14.     writeln(a, '%');
  15.   end;
  16. end.

Note: before anybody gets emotional about preserving the Pascal language, this is just a conversation, relax and enjoy.
Title: Re: while loop with code before comparison
Post by: Blaazen on August 11, 2020, 04:10:50 pm
Since the loop must go at least once and I don't mind endless loops I would use:
Code: Pascal  [Select][+][-]
  1.   writeln('here are random percentages <= 75%');
  2.   randomize;
  3.   repeat
  4.     a := random(101);
  5.     if a<=75
  6.       then writeln(a, '%')
  7.       else break;
  8.   until False;
Title: Re: while loop with code before comparison
Post by: lucamar on August 11, 2020, 04:26:05 pm
I don't see the need for either solution. One could just as well do:

Code: Pascal  [Select][+][-]
  1.   writeln('here are random percentages <= 75%');
  2.   randomize;
  3.   repeat
  4.     a := random(101);
  5.     if a <= 75 then writeln(a, '%');
  6.   until a > 75;

One might include, before the WriteLn the guard against a number being greater that 75 but other than that ... 8-)
Title: Re: while loop with code before comparison
Post by: Martin_fr on August 11, 2020, 04:32:34 pm
Code: Pascal  [Select][+][-]
  1.     var a: integer;
  2.     begin
  3.       writeln('here are random percentages <= 75%');
  4.       randomize;
  5.       a := random(101);
  6.       while a <= 75 do
  7.       begin
  8.         writeln(a, '%');
  9.         a := random(101);
  10.       end;
  11.     end.
Title: Re: while loop with code before comparison
Post by: circular on August 11, 2020, 07:40:27 pm
Thanks for the suggestions.

Though for each of them, something is not quite satisfying to me:
- @Blaazen version includes an endless loop but it is not one
- @lucamar version includes twice the test
- @Martin_fr version includes a duplication of the assignment to a
Title: Re: while loop with code before comparison
Post by: Fred vS on August 11, 2020, 07:47:44 pm
Quote
- @Martin_fr version includes a duplication of the assignment to a

Code: Pascal  [Select][+][-]
  1. var a: integer = -1;
  2.     begin
  3.       writeln('here are random percentages <= 75%');
  4.       randomize;
  5.        while a <= 75 do
  6.       begin
  7.         writeln(a, '%');  // Ok, there will be the first not random = -1
  8.         a := random(101);
  9.       end;
  10.     end.

Title: Re: while loop with code before comparison
Post by: Kays on August 11, 2020, 08:02:17 pm
[…] So how about a language construct that would express that. […]
Can’t you just define your custom enumerator?
Code: Pascal  [Select][+][-]
  1. program randomNumbers(input, output, stdErr);
  2. {$mode objFPC}
  3.  
  4. type
  5.         randomNumber = type nativeInt;
  6.        
  7.         randomPercentageIterator = class
  8.                         private
  9.                                 threshold: randomNumber;
  10.                         public
  11.                                 // METHODS
  12.                                 procedure reset;
  13.                                 function getCurrent(): randomNumber;
  14.                                 function moveNext(): longBool;
  15.                                 // PROPERTIES
  16.                                 property current: randomNumber read getCurrent;
  17.                                 // CONSTRUCTORS/DESTRUCTORY
  18.                                 constructor create(const n: randomNumber);
  19.                                 destructor destroy; override;
  20.                 end;
  21.  
  22. procedure randomPercentageIterator.reset;
  23. begin
  24.         randomize;
  25. end;
  26.  
  27. function randomPercentageIterator.getCurrent(): randomNumber;
  28. begin
  29.         repeat
  30.                 getCurrent := random(101);
  31.         until getCurrent <= threshold;
  32. end;
  33.  
  34. function randomPercentageIterator.moveNext(): longBool;
  35. begin
  36.         moveNext := true;
  37. end;
  38.  
  39. constructor randomPercentageIterator.create(const n: randomNumber);
  40. begin
  41.         threshold := n;
  42.         reset;
  43. end;
  44.  
  45. destructor randomPercentageIterator.destroy;
  46. begin
  47.         inherited;
  48. end;
  49.  
  50. operator enumerator(const n: randomNumber): randomPercentageIterator;
  51. begin
  52.         result := randomPercentageIterator.create(n);
  53. end;
  54.  
  55. var
  56.         n: randomNumber;
  57. begin
  58.         for n in randomNumber(75) do
  59.         begin
  60.                 writeLn(n:3, ' %');
  61.         end;
  62. end.
Title: Re: while loop with code before comparison
Post by: Martin_fr on August 11, 2020, 08:14:29 pm
Code: Pascal  [Select][+][-]
  1. function GetValue(var val: integer): boolean; inline;
  2. begin
  3.   val := random(101);
  4.   result := val <= 75; // the value is duplicated....
  5. end;
  6.  
  7. ......
  8.     var a: integer = 0;
  9.         begin
  10.           writeln('here are random percentages <= 75%');
  11.           randomize;
  12.            while GetValue(a) do
  13.               writeln(a, '%');
  14.         end.



Title: Re: while loop with code before comparison
Post by: eny on August 11, 2020, 08:52:04 pm
Two solutions that:
- do not require an endless loop;
- have only one test;
- only one assignment location of a random value.
But since this is a thread about opinion, I'm sure circular will have comments :D

Code: Pascal  [Select][+][-]
  1. program simple;
  2.  
  3. procedure Foo;
  4. label NotYet75;
  5. var a: integer;
  6. begin
  7.   Writeln('Foo');
  8. NotYet75:
  9.   a := random(101);
  10.   if a <= 75 then
  11.   begin
  12.     writeln(a,'%');
  13.     goto NotYet75;
  14.   end;
  15. end;
  16.  
  17. procedure Bar;
  18.  
  19.   function DoRandom(var n: integer): integer;
  20.   begin
  21.     n := random(101);
  22.     exit(n)
  23.   end;
  24.  
  25. var
  26.   a: integer;
  27. begin
  28.   writeln('Bar');
  29.   while DoRandom(a) <= 75 do
  30.     writeln(a, '%');
  31. end;
  32.  
  33. begin
  34.   Randomize;
  35.   Foo;
  36.   Bar;
  37.   readln;
  38. end.
  39.  
Title: Re: while loop with code before comparison
Post by: circular on August 11, 2020, 09:05:10 pm
There are some clever solutions that were just proposed. We are getting somewhere  :)

- @Kays: defining a custom enumerator is satisfactory from a meaning point of view, but it is much stuff to write and I am a bit lazy
- @Fred vS: that's an elegant solution and I would probably choose to do that when that's possible, though it requires a value. What to do if the value is an interface? Maybe create a dummy interface that would pass the test.
- @Martin_fr: this solution seems to be actually the best, it works in all cases, no duplication of code. I would suggest an out parameter to avoid to have to initialize a.
Code: Pascal  [Select][+][-]
  1. function GetValue(out val: integer): boolean; inline;
  2. begin
  3.   val := random(101);
  4.   result := val <= 75; // test is defined here, that's no duplication
  5. end;
  6.  
  7. ......
  8.     var a: integer;
  9.     begin
  10.       writeln('here are random percentages <= 75%');
  11.       randomize;
  12.       while GetValue(a) do
  13.          writeln(a, '%');
  14.     end.
- @eny: haha the goto is a way to do something when the language structure is not available, so well not that satisfactory for me. The function that returns the value is clever, it works. There is some duplication of the value, but in this case I guess that would be ok.
Title: Re: while loop with code before comparison
Post by: Fred vS on August 11, 2020, 09:16:58 pm
Quote
I would use an out parameter to avoid to have to initialize a.

Not sure to understand, does out parameter initialize the integer-value?
If yes, with what value?
Title: Re: while loop with code before comparison
Post by: circular on August 11, 2020, 09:19:42 pm
The out parameter does not care if the value has been initialized, because it will replace it. So you won't get any warning.
Title: Re: while loop with code before comparison
Post by: Fred vS on August 11, 2020, 09:23:15 pm
Yep, nice and with your solution the first loop is random too.
Title: Re: while loop with code before comparison
Post by: circular on August 11, 2020, 09:30:56 pm
Well that's essentially Martin_fr's solution.

So, yes, we have a satisfactory solution, using a function that either returns a boolean if the test passes, or that returns the generated value.

Still, the function can be far away if there is much code around, so I would still love a language construct for that.
Title: Re: while loop with code before comparison
Post by: Fred vS on August 11, 2020, 09:33:30 pm
Quote
so I would still love a language construct for that.

OK, everybody seems cool, open-mind and ready today.

What is your proposition?

 ;)
Title: Re: while loop with code before comparison
Post by: circular on August 11, 2020, 09:38:50 pm
 :D that went well indeed.

I was imagining what I suggested in the first post, to have a for while construct. The iteration computation after for and the rest after while.

Though maybe there are more elegant ways to do that.
Title: Re: while loop with code before comparison
Post by: 440bx on August 11, 2020, 11:23:45 pm
Suppose I want to display random numbers while they are less than some number. Such program can be written as:
Code: Pascal  [Select][+][-]
  1. var a: integer;
  2. begin
  3.   writeln('here are random percentages <= 75%');
  4.   randomize;
  5.   while true do
  6.   begin
  7.     a := random(101);
  8.     if a > 75 then break;
  9.     writeln(a, '%');
  10.   end;
  11. end.

This works, but I don't like the misleading "while true". The real condition is a <= 75. In C the solution to this is to used an assignment inside the condition, but I don't like it either.

- @Martin_fr: this solution seems to be actually the best, it works in all cases, no duplication of code. I would suggest an out parameter to avoid to have to initialize a.
Code: Pascal  [Select][+][-]
  1. function GetValue(out val: integer): boolean; inline;
  2. begin
  3.   val := random(101);
  4.   result := val <= 75; // test is defined here, that's no duplication
  5. end;
  6.  
  7. ......
  8.     var a: integer;
  9.     begin
  10.       writeln('here are random percentages <= 75%');
  11.       randomize;
  12.       while GetValue(a) do
  13.          writeln(a, '%');
  14.     end.
Just a "conversional" note.  You realize that Martin_fr's solution, which is elegant, is essentially exactly the same as the "while true do" loop which you are not fond of. 

Personally, I prefer the "while true do" solution because I don't have to go look for the function used in the "while" condition (it could be hundreds of lines away from the "while" statement - not common but bad source organization isn't  all that uncommon.)  I don't think "while true do" is misleading because, at least most of the time, the programmer would expect there is a condition being tested in the loop that will cause it to end (the cases where an infinite loop is useful are not very common.)


Title: Re: while loop with code before comparison
Post by: Martin_fr on August 12, 2020, 01:42:00 am
because I don't have to go look for the function used in the "while" condition (it could be hundreds of lines away from the "while" statement - not common but bad source organization isn't  all that uncommon.) 

<sarcasm>
Well, the ultimate solution is of course to have some classes and objects. There would have to be a TRandomProvider, TRangeChecker and most important a TProviderState.  The RangeChecker would update the state, and the provider could then decide what action to take by using the visitor pattern on the State.
Wrap that into an enumerator, and use a Mediator for the communication between enumerator and provider.
Just to keep it simple.
</sarcasm>
;)
Title: Re: while loop with code before comparison
Post by: circular on August 12, 2020, 07:19:41 am
 :D
And have a class that contains the number as well, in case it is undefined. TNumber would have an IsLowerThanOrEqual function, that would return False when the number is undefined.

Just a "conversional" note.  You realize that Martin_fr's solution, which is elegant, is essentially exactly the same as the "while true do" loop which you are not fond of.
Nope, it doesn't suggest an infinite loop.

Quote
Personally, I prefer the "while true do" solution because I don't have to go look for the function used in the "while" condition (it could be hundreds of lines away from the "while" statement - not common but bad source organization isn't  all that uncommon.)
That's what I just said.

Quote
I don't think "while true do" is misleading because, at least most of the time, the programmer would expect there is a condition being tested in the loop that will cause it to end (the cases where an infinite loop is useful are not very common.)
Yeah, it is because we know that's a way to deal with certain cases to put an infinite loop.
Title: Re: while loop with code before comparison
Post by: 440bx on August 12, 2020, 08:00:48 am
Nope, it doesn't suggest an infinite loop.
Anyone who reads that should have warning bells going off because there is a "mystery" function (until it is inspected) that may always return true.  Additionally, there is no indication whatsoever of what is the condition, if any, that will end the loop.

Yeah, it is because we know that's a way to deal with certain cases to put an infinite loop.
Seeing a statement "while true do" (should) immediately cause the programmer to search for the condition(s) that will end the loop and, if present, they must be in the loop (local.)

Martin_fr's solution is elegant but, it moves information into a different context (the function definition) which should be in the loop condition not someplace else.

At least when a programmer sees "while true do" he/she knows upfront it's an infinite loop.  In the other case, it may or may not be an infinite loop and the "decision" is made someplace else instead of in the "while".

The best/safest/clearest solution is the one you mentioned in your OP that you didn't like.
Title: Re: while loop with code before comparison
Post by: marcov on August 12, 2020, 09:45:00 am
Personally, I prefer the "while true do" solution because I don't have to go look for the function used in the "while" condition (it could be hundreds of lines away from the "while" statement - not common but bad source organization isn't  all that uncommon.)  I don't think "while true do" is misleading because, at least most of the time, the programmer would expect there is a condition being tested in the loop that will cause it to end (the cases where an infinite loop is useful are not very common.)

This is so wrong, and totally not like Wirth intended it.

Wirth intended to use the keyword LOOP which you luckily can add yourself with a bit of macro shenigans

Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2. {$macro on}
  3.  
  4. {$define loop:=while true do}
  5.  
  6. var i : integer;
  7. begin
  8.   LOOP
  9.   begin
  10.     i:=i+1;
  11.     if i>10 then
  12.       exit;
  13.     writeln(i);
  14.   end;
  15. end.

or another classic:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2.  
  3. const ENDOFTIME= false;
  4.        
  5.  begin
  6.   REPEAT
  7.   UNTIL ENDOFTIME;
  8. end.

p.s. this message is not 100% serious.
Title: Re: while loop with code before comparison
Post by: circular on August 12, 2020, 09:51:39 am
@440bx

I agree with the mystery problem, that's why it is not completely satisfying to have a function containing the comparison, in particular if there is a lot of code around.

I guess that @eny suggestions solves this:
Code: Pascal  [Select][+][-]
  1.   function AssignRandom(out n: integer): integer; inline;
  2.   begin
  3.     n := random(101);
  4.     exit(n)
  5.   end;
  6.  
  7. var
  8.   a: integer;
  9. begin
  10.   while AssignRandom(a) <= 75 do
  11.     writeln(a, '%');
  12. end;

In this case, there is no mystery on what AssignRandom does, and the test is in the condition.

I guess I like it as much as the infinite loop. Though somehow both are kind of tricks that tells me that a language structure is missing.

Similary, if we would use this new construct to do a basic for loop, that would not be satisfying:
Code: Pascal  [Select][+][-]
  1. var i: integer;
  2. begin
  3.   i := 0;
  4.   for inc(i) while i <= 10 do writeln(i);
  5. end;
Title: Re: while loop with code before comparison
Post by: 440bx on August 12, 2020, 10:12:04 am
p.s. this message is not 100% serious.
Good :)  because macro shenanigans are not in my list of acceptable programming habits.



Though somehow both are kind of tricks that tells me that a language structure is missing.
The "solution" (note the quotes) or, I should say, the best known one, is to allow assignments within expressions.  That "solution", while at first seems like a good idea, it is Pandora's box (at least in C) because the immutability of the expression terms is neither guaranteed and, often not even obvious one way or the other.

Eny's suggestion is definitely good (that said, I don't see any reason to have "exit(n)" in there).  Actually, now that you've re-stated it, I think it is a better solution than the one presented by Martin_fr

In spite of that, I'd still go with the "while true do" because all the information a programmer needs is right there.  There is no need to look outside the "while" loop to figure out what controls it and how it is controlled.

IMO and experience, programs are much easier to understand and maintain when relationships among statements are grouped together.
Title: Re: while loop with code before comparison
Post by: circular on August 12, 2020, 10:12:23 am
@marcov

Oh no we had the conversation going nicely until now  :D

Using macros, sure is a way to solve the problem.  :D

Code: Pascal  [Select][+][-]
  1. {$MACRO ON}
  2. {$DEFINE foreach:=while true do begin}
  3. {$DEFINE where:=;if not (}
  4. {$DEFINE iterate:=) then break;}
  5. var a: integer;
  6. begin
  7.   writeln('here are random percentages <= 75%');
  8.   randomize;
  9.   foreach a := random(101) where a <= 75 iterate
  10.     writeln(a, '%');
  11.   end;
  12. end.
  13.  
Title: Re: while loop with code before comparison
Post by: circular on August 12, 2020, 10:15:02 am
IMO and experience, programs are much easier to understand and maintain when relationships among statements are grouped together.
Hence the new language construct idea :)
Title: Re: while loop with code before comparison
Post by: Martin_fr on August 12, 2020, 10:20:42 am
Still, the function can be far away if there is much code around, so I would still love a language construct for that.

Well, that would be solved by anonymous functions....
Title: Re: while loop with code before comparison
Post by: marcov on August 12, 2020, 10:21:29 am
My point is actually that Wirth introduced such a construct (LOOP..END;) in Modula-2.
Title: Re: while loop with code before comparison
Post by: 440bx on August 12, 2020, 10:32:47 am
My point is actually that Wirth introduced such a construct (LOOP..END;) in Modula-2.
Ok, does that mean you'd support the addition of a LOOP instruction in Free Pascal ? 
Title: Re: while loop with code before comparison
Post by: circular on August 12, 2020, 11:35:33 am
Well, that would be solved by anonymous functions....
Would it look like that?
Code: Pascal  [Select][+][-]
  1. var a: integer;
  2. begin
  3.   writeln('here are random percentages <= 75%');
  4.   randomize;
  5.   while function(out val: integer): boolean
  6.         begin
  7.           val := random(101);
  8.           result := val <= 75;
  9.         end (a) do
  10.      writeln(a, '%');
  11.   end;
  12. end.
That would not be readable.

My point is actually that Wirth introduced such a construct (LOOP..END;) in Modula-2.
Indeed. That would avoid the strange statement "while true" though that is still an infinite loop.
Title: Re: while loop with code before comparison
Post by: marcov on August 12, 2020, 12:16:08 pm
My point is actually that Wirth introduced such a construct (LOOP..END;) in Modula-2.
Ok, does that mean you'd support the addition of a LOOP instruction in Free Pascal ?

I'd support the addition of a whole Modula2 mode to FPC. :)
Title: Re: while loop with code before comparison
Post by: Ñuño_Martínez on August 12, 2020, 12:18:14 pm
I think Circular needs some kind of C-like for loop:
Code: C  [Select][+][-]
  1.   for (<initialization>; <condition>; <iteration>) <code-block>;
  2.  
I don't like it a lot mainly because you can use almost any code inside the for declaration.  I know that's not possible in Pascal, but just to illustrate:
Code: C  [Select][+][-]
  1.   for (
  2.     puts ("Hello, I'm inside the loop initialization");
  3.     b = a > some_function () ? (printf ("a = %d", a), TRUE) : FALSE;
  4.     puts ("I'm here but not needed")
  5.   )
  6.     a++;
  7.  
Actually I'm not sure it will compile (iirc printf is void but the "," operator should deal with it), but you see it is quite confusing.  And I've seen code like that.

I'm not sure how such loop would look in Pascal but let me try:
Code: Pascal  [Select][+][-]
  1. WHEN <assignation> IS <condition> DO <code>
  2.  

For example:
Code: Pascal  [Select][+][-]
  1. PROGRAM TestNewLoopType;
  2. VAR
  3.   Value: INTEGER;
  4. BEGIN
  5.   WriteLn ('Here are random percentages <= 75%');
  6.   Randomize;
  7.   WHEN Value := Random (101) IS Value <= 75 DO
  8.     WriteLn (Value, '%')
  9. END.
  10.  

[edit] Had another idea:
Code: Pascal  [Select][+][-]
  1.   WHEN <condition> IN <assignation> DO <code>
  2.  

Code: Pascal  [Select][+][-]
  1. PROGRAM TestNewLoopType;
  2. VAR
  3.   Value: INTEGER;
  4. BEGIN
  5.   WriteLn ('Here are random percentages <= 75%');
  6.   Randomize;
  7.   WHEN Value <=75 IN Value := Random (101) DO
  8.     WriteLn (Value, '%')
  9. END.
Title: Re: while loop with code before comparison
Post by: Martin_fr on August 12, 2020, 12:30:00 pm
That would not be readable.
I agree.... Just pointed out the possibility.
Its basically the: assignment and condition in one....


But what you really want is something that:
- Ideally makes it clear what variable is your loop var. Maybe even protects it, like for does
- Has a clear "loop condition" (rather than zero, one or more "break" conditions somewhere buried in the middle of the loop code)
- has an initial value for the loop var
- has an update for the loop var
=> Or in your case initial and update is the same.

Even the  "for(initial, condition, update)"  does not fulfil that


In other words, the conflict you have is IMHO that:
- You need the loop condition in the middle (after getting the random number, but before printing it)
- You want the loop condition to be clearly noticeable, which means it should be part of the loop statement (no infinite loop statement)

Those 2 statements directly contradict each other.
So the problem is logical at first, rather than just missing syntax....
- Init goes before the loop
- update goes into the loop
If both are combined, where should they go?



If you ignore the fact that in your case "init loop var" and "update loop var" is the same. And therefore leads to syntactical duplication (the meaning is not duplicated), then you should end up with an earlier proposal:
Code: Pascal  [Select][+][-]
  1. init;
  2. while cond do begin
  3.    work
  4.    update
  5. end

or
Code: Pascal  [Select][+][-]
  1. a := random(101); // init
  2. while a <= 75 do begin
  3.   writeln(a); // work
  4.   a := random(101); // update => different meaning, even if same text
  5. end;
  6.  

Or (not what I would do...)
Code: Pascal  [Select][+][-]
  1. goto loopstart;
  2. while a <= 75 do begin
  3.   writeln(a);
  4. loopstart:
  5.   a := random(101);
  6. end;
  7.  
Title: Re: while loop with code before comparison
Post by: BeniBela on August 12, 2020, 01:01:58 pm
Or (not what I would do...)
Code: Pascal  [Select][+][-]
  1. goto loopstart;
  2. while a <= 75 do begin
  3.   writeln(a);
  4. loopstart:
  5.   a := random(101);
  6. end;
  7.  

I love the look of that

But not sure if fpc can compile such unusual constructs properly
Title: Re: while loop with code before comparison
Post by: Blaazen on August 12, 2020, 01:15:00 pm
@ But not sure if fpc can compile such unusual constructs properly

It can, it only give false-positive warning on this line:
Code: Pascal  [Select][+][-]
  1. while a <= 75 do begin

Warning: Local variable "a" does not seem to be initialized
Title: Re: while loop with code before comparison
Post by: Fred vS on August 12, 2020, 02:55:11 pm
Code: Pascal  [Select][+][-]
  1.   WHEN <condition> IN <assignation> DO <code>
  2.  

Code: Pascal  [Select][+][-]
  1. PROGRAM TestNewLoopType;
  2. VAR
  3.   Value: INTEGER;
  4. BEGIN
  5.   WriteLn ('Here are random percentages <= 75%');
  6.   Randomize;
  7.   WHEN Value <=75 IN Value := Random (101) DO
  8.     WriteLn (Value, '%')
  9. END.

Hum, I like it, if I may (and if everybody is cool), I would propose if something could be changed, to refactor the "IN" reserved-word-behavior and give it some extra feature.

Afaik, the "IN" reserved-word was not a creation of Wirth (but I may be wrong).

So it could be something like this (without the new "WHEN" keyword):

Code: Pascal  [Select][+][-]
  1. PROGRAM TestNewLoopType;
  2. VAR
  3.   Value: INTEGER;
  4. BEGIN
  5.   WriteLn ('Here are random percentages <= 75%');
  6.   Randomize;
  7.   WHILE Value <=75 IN Value := Random (101) DO
  8.     WriteLn (Value, '%');
  9. END.

And it could be used for IF too:

Code: Pascal  [Select][+][-]
  1. PROGRAM TestNewIFType;
  2. VAR
  3.   Value: INTEGER;
  4. BEGIN
  5.   WriteLn ('Here are random percentages <= 75%');
  6.   Randomize;
  7.   IF Value <=75 IN Value := Random (101) THEN
  8.     WriteLn (Value, '%');
  9. END.

And for 'FOR' too.

Fre;D
Title: Re: while loop with code before comparison
Post by: MarkMLl on August 12, 2020, 05:07:18 pm
Code: Pascal  [Select][+][-]
  1.   WHEN Value <=75 IN Value := Random (101) DO
  2.  

I don't quite see what you're trying to do, but my opinion is that that is far too close to the ALGOL/C multiple assignment

Code: [Select]
  a == b = c;

...which is the cause of a number of bugs massive even by C standards.

MarkMLl
Title: Re: while loop with code before comparison
Post by: ASBzone on August 12, 2020, 06:24:29 pm
I'd support the addition of a whole Modula2 mode to FPC. :)

I'm not sure how to interpret that with the smiley in there...  LOL

 :-X Well, at least I have no legacy code that wouldn't stand to gain from such a course. 
Title: Re: while loop with code before comparison
Post by: circular on August 12, 2020, 06:38:38 pm
I think Circular needs some kind of C-like for loop:
Code: C  [Select][+][-]
  1.   for (<initialization>; <condition>; <iteration>) <code-block>;
  2.  
I see what you mean but not exactly. For such construct, I am ok with:
Code: Pascal  [Select][+][-]
  1. begin
  2.   #initialization
  3.   while #condition do
  4.   begin
  5.     #code-block
  6.     #iteration
  7.   end
  8. end

Quote
Code: Pascal  [Select][+][-]
  1. PROGRAM TestNewLoopType;
  2. VAR
  3.   Value: INTEGER;
  4. BEGIN
  5.   WriteLn ('Here are random percentages <= 75%');
  6.   Randomize;
  7.   WHEN Value := Random (101) IS Value <= 75 DO
  8.     WriteLn (Value, '%')
  9. END.
  10.  
Yeah something like, though I feel like it does not express that we are doing this repeatedly. Hence the need for "for" or "foreach".

@Martin_fr  :D the goto is clever, though a bit upside down
Title: Re: while loop with code before comparison
Post by: MarkMLl on August 12, 2020, 08:37:29 pm
I'd support the addition of a whole Modula2 mode to FPC. :)

I'm not sure how to interpret that with the smiley in there...  LOL

I think that a complete Modula-2 mode might be overkill. Specifically, FPC's uses and declaration/definition syntax and semantics are probably at least as comprehensive as Modula-2's, and while LOOP would be desirable it would probably be worth retaining the current usage of CONTINUE and BREAK. Case-sensitivity enabled or disabled by pragma, since TBH I'd like to see inconsistent case usage at least trigger a warning in the other modes.

Apart from that most things that have been added post-J&W are nearer Modula-2's syntax than Pascal anyway. I'm thinking of the explicit end after finally and exception blocks among other things.

MarkMLl
Title: Re: while loop with code before comparison
Post by: Ñuño_Martínez on August 13, 2020, 11:39:24 am
Code: Pascal  [Select][+][-]
  1.   WHEN Value <=75 IN Value := Random (101) DO
  2.  

I don't quite see what you're trying to do, but my opinion is that that is far too close to the ALGOL/C multiple assignment

Code: [Select]
  a == b = c;

...which is the cause of a number of bugs massive even by C standards.

MarkMLl
After reading this I've found the flaw in my proposal:  IN keyword is an operator (or almost) that returns a boolean.  So Fred's suggestion to refactor it would be hard and generate some ambiguity wich is against Pascal spirit. :(
Title: Re: while loop with code before comparison
Post by: MarkMLl on August 13, 2020, 12:47:16 pm
I think the canonical solution is this one, based on @lucamar's proposal:

Code: Pascal  [Select][+][-]
  1.   writeln('here are random percentages <= 75%');
  2.   randomize;
  3.   repeat
  4.     a := random(101);
  5.     if a <= 75 then
  6.       writeln(a, '%')
  7.     else
  8.       break
  9.   until false;
  10.  

It does obviously assume that the compiler optimises usage of the local variable well, and it would upset any purist who equates break/continue with goto.

I don't like any suggestion of multiple assignment in a language that supports polymorphism and/or type promotion, or (in particular) allows the result of a function to be discarded.

The only other realistic possibility would be something like

Code: Pascal  [Select][+][-]
  1.   writeln('here are random percentages <= 75%');
  2.   randomize;
  3.   repeat
  4.     try
  5.       writeln(randomValue, '%')
  6.     except
  7.       exit
  8.     end
  9.   until false;
  10.  

where randomValue is a function that raises an exception if it thinks its caller needs to exit. Note that I've not decorated it with parentheses in an effort to make life as confusing as possible >:-)

MarkMLl
Title: Re: while loop with code before comparison
Post by: glorfin on August 13, 2020, 01:20:17 pm
I'd support the addition of a whole Modula2 mode to FPC. :)

Then why not Oberon?
And I am almost serious.
Title: Re: while loop with code before comparison
Post by: PascalDragon on August 13, 2020, 01:35:00 pm
I'd support the addition of a whole Modula2 mode to FPC. :)

Then why not Oberon?
And I am almost serious.

marcov is a Modula2 fan, so that explains why he'd prefer Modula2 to Oberon. ;)
Title: Re: while loop with code before comparison
Post by: MarkMLl on August 13, 2020, 01:39:02 pm
I'd support the addition of a whole Modula2 mode to FPC. :)

Then why not Oberon?
And I am almost serious.

Because relative to FPC, the major thing that Modula-2 does is sort out the damaging-else problem. Oberon AIUI does other things like deprecating enumerations, subranges, and sets other than bitsets. IMO, being able to define an array as subscripted by an enumeration/subrange or a set as containing members of a particular enumeration/subrange are major expressive elements.

MarkMLl
Title: Re: while loop with code before comparison
Post by: Fred vS on August 13, 2020, 01:39:10 pm
After reading this I've found the flaw in my proposal:  IN keyword is an operator (or almost) that returns a boolean.  So Fred's suggestion to refactor it would be hard and generate some ambiguity wich is against Pascal spirit. :(

You may use also the Martin's idea in conjunction of yours:

Code: Pascal  [Select][+][-]
  1. WHEN Value <=75 IN GetValue(value) DO

But yes, the best would be to refactor "IN" behaviour.

For example I would like to have the possibility of this:

Code: Pascal  [Select][+][-]
  1. Program inextended;
  2. ...
  3. uses
  4. myunit in '../mydir/myotherdir', ...

But all this is for the sport, it is only proposition in the air, without any bad intention.

Fre;D

Title: Re: while loop with code before comparison
Post by: PascalDragon on August 13, 2020, 01:54:24 pm
For example I would like to have the possibility of this:

Code: Pascal  [Select][+][-]
  1. Program inextended;
  2. ...
  3. uses
  4. myunit in '../mydir/myotherdir', ...

This should work:

Code: Pascal  [Select][+][-]
  1. uses
  2.   myunit in '../mydir/myotherdir/myunit.pas';

This is Delphi compatible.
Title: Re: while loop with code before comparison
Post by: Fred vS on August 13, 2020, 02:43:11 pm
[EDIT: I deleted my previous posts because wrong compilation]

Yep, that works, even in objpas mode:

Code: Pascal  [Select][+][-]
  1.     unit test;
  2.      
  3.     {$IFDEF FPC}{$MODE objpas}{$H+}{$ENDIF}
  4.      
  5.     interface
  6.      
  7.     uses
  8.     bgrabitmap in '/home/fred/bgrabitmap-dev-bgrabitmap/bgrabitmap/bgrabitmap.pas', ...

OK and excellent.

By the way I will not be against:

Code: Pascal  [Select][+][-]
  1. uses
  2. mayunit in '/my/directory/';
Title: Re: while loop with code before comparison
Post by: lucamar on August 14, 2020, 02:57:00 am
By the way I will not be against:
Code: Pascal  [Select][+][-]
  1. uses
  2. mayunit in '/my/directory/';

That's what the compiler's "unit search path" is for, though I agree it might be nice to be able to do it in code to, for example, activate temporarily alternative versions instead of the default units or tricks like that ;)
TinyPortal © 2005-2018