### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: while loop with code before comparison  (Read 2126 times)

#### circular

• Hero Member
• Posts: 3451
##### while loop with code before comparison
« 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.
Conscience is the debugger of the mind

#### Blaazen

• Hero Member
• Posts: 2922
• POKE 54296,15
##### Re: while loop with code before comparison
« Reply #1 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;
Lazarus 2.1.0 r63940 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

#### lucamar

• Hero Member
• Posts: 3030
##### Re: while loop with code before comparison
« Reply #2 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 ...
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!)
Lazarus 2.0.8/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

#### Martin_fr

• Hero Member
• Posts: 6631
• Debugger - SynEdit - and more
##### Re: while loop with code before comparison
« Reply #3 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.

#### circular

• Hero Member
• Posts: 3451
##### Re: while loop with code before comparison
« Reply #4 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
Conscience is the debugger of the mind

#### Fred vS

• Hero Member
• Posts: 1841
##### Re: while loop with code before comparison
« Reply #5 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.

« Last Edit: August 11, 2020, 08:13:53 pm by Fred vS »
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### Kays

• Full Member
• Posts: 214
• Whasup!?
##### Re: while loop with code before comparison
« Reply #6 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.
« Last Edit: August 11, 2020, 08:07:29 pm by Kays »
Yours Sincerely
Kai Burghardt

#### Martin_fr

• Hero Member
• Posts: 6631
• Debugger - SynEdit - and more
##### Re: while loop with code before comparison
« Reply #7 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.

#### eny

• Hero Member
• Posts: 1609
##### Re: while loop with code before comparison
« Reply #8 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.

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;
38. end.
39.
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

#### circular

• Hero Member
• Posts: 3451
##### Re: while loop with code before comparison
« Reply #9 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.
« Last Edit: August 11, 2020, 09:12:46 pm by circular »
Conscience is the debugger of the mind

#### Fred vS

• Hero Member
• Posts: 1841
##### Re: while loop with code before comparison
« Reply #10 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?
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### circular

• Hero Member
• Posts: 3451
##### Re: while loop with code before comparison
« Reply #11 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.
Conscience is the debugger of the mind

#### Fred vS

• Hero Member
• Posts: 1841
##### Re: while loop with code before comparison
« Reply #12 on: August 11, 2020, 09:23:15 pm »
Yep, nice and with your solution the first loop is random too.
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

#### circular

• Hero Member
• Posts: 3451
##### Re: while loop with code before comparison
« Reply #13 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.
Conscience is the debugger of the mind

#### Fred vS

• Hero Member
• Posts: 1841
##### Re: while loop with code before comparison
« Reply #14 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.