Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

Author Topic: Nested procedures  (Read 1681 times)

Ten_Mile_Hike

• Jr. Member
• Posts: 69
Nested procedures
« on: June 12, 2024, 09:04:37 pm »
I realize that "Str" is a procedure not a function, but why does this work

Code: Pascal  [Select][+][-]
1. procedure TForm1.B6Click(Sender:TObject);
2. Type Seasons=(summer,fall,winter,spring);
3. var
4.    names:Seasons;
5.    s:string;
6. Begin
7.   for names in seasons Do
8.   Begin
9.     str(names,s);
11.   end;
12. end;

but this is an error

Code: Pascal  [Select][+][-]
1. procedure TForm1.B6Click(Sender:TObject);
2. Type Seasons=(summer,fall,winter,spring);
3. var
4.    names:Seasons;
5.    s:string;
6. Begin
7.   For names in seasons Do  M1.lines.Add(str(names,s) );
8. end;

Fibonacci

• Sr. Member
• Posts: 453
• Internal Error Hunter
Re: Nested procedures
« Reply #1 on: June 12, 2024, 09:13:08 pm »
A procedure doesnt return anything, you cannot use it as a parameter when calling M1.lines.Add()

Ten_Mile_Hike

• Jr. Member
• Posts: 69
Re: Nested procedures
« Reply #2 on: June 12, 2024, 09:37:40 pm »
Hello Fibonacci,

Yes; that is why I noted "I know that it is a procedure not a function"
My question is what is it about the pascal specification that forbids
the statement from being "evaluated" even if it doesn't "return" a
value?
« Last Edit: June 12, 2024, 09:45:14 pm by Ten_Mile_Hike »

Fibonacci

• Sr. Member
• Posts: 453
• Internal Error Hunter
Re: Nested procedures
« Reply #3 on: June 12, 2024, 09:49:06 pm »
Maybe it can be evaluated, but anyway Add() requires a parameter of a specified type, and as you know a procedure doesnt return anything

BTW. Just now I found another Internal Error

Code: Pascal  [Select][+][-]
1. procedure proc;
2. begin
3. end;
4.
5. procedure test(const o);
6. begin
7. end;
8.
9. begin
10.   test(proc); // project1.lpr(10,3) Error: Internal error 2011010304
11. end.

egsuh

• Hero Member
• Posts: 1396
Re: Nested procedures
« Reply #4 on: June 13, 2024, 06:30:08 am »
Pascal compiler is known to be strict in data type. So, M1.Lines.Add will require a string-type constant as a parameter, nothing else (unless it is overloaded with other types).

You may define your own function.

Code: Pascal  [Select][+][-]
1. function SeasonStr(season: Seasons): string;
2. begin
3.     Str(season, result);
4. end;
5.
and then

for names in Seasons do M1.Lines.Add(SeasonStr(names));

should work (I hope).

• Hero Member
• Posts: 15210
• Censorship about opinions does not belong here.
Re: Nested procedures
« Reply #5 on: June 13, 2024, 01:10:28 pm »
Yes, that works.

Even C - the most liberal and error prone language - will not evaluate a void function (what we call procedure) as a parameter.
I am not aware of any language that will evaluate a procedure like OP wants.
I came up with about the same as you did:
Code: Pascal  [Select][+][-]
1. {\$mode objfpc}
2. uses sysutils;
3. Type Seasons=(summer,fall,winter,spring);
4. function str(const value:seasons):string;inline;
5. begin
6.   system.str(value,result);
7. end;
8. var
9.    names:Seasons;
10.    s:string;
11. Begin
12.   For names in seasons Do writeln(str(names) );
13. end.

« Last Edit: June 13, 2024, 01:54:05 pm by Thaddy »
Of course the national anthem of the U.S.A. was written by Jimi Hendrix, didn't you know that?

• Hero Member
• Posts: 15210
• Censorship about opinions does not belong here.
Re: Nested procedures
« Reply #6 on: June 13, 2024, 01:26:24 pm »
Or as a teaser, works only in trunk:
Code: Pascal  [Select][+][-]
1. {\$mode objfpc}
2. {\$if fpc_fullversion < 30301}
3.   {\$error this version can not handle this code, needs 3.3.1 or higher}
4. {\$ifend}
5. {\$modeswitch implicitfunctionspecialization}
6. uses sysutils;
7. Type Seasons=(summer,fall,winter,spring);
8.
9. generic function str<T>(const value:T):string;inline;
10. begin
11.   system.str(Value,result);
12. end;
13. var
14.    names:Seasons;
15. Begin
16.   { implicit specialization }
17.   For names in seasons do writeln(str(names));
18. end.
19.
T needs to be ordinal. We can not yet write a restriction like str<T:ordinal> but it is considered to be implemented. Once it is, this code would be very safe.
I show this, because this new feature of implicit specialization is very powerful and I recently started to use it a lot. (but I don't have to write production code anymore.....)
« Last Edit: June 13, 2024, 05:13:48 pm by Thaddy »
Of course the national anthem of the U.S.A. was written by Jimi Hendrix, didn't you know that?

Ten_Mile_Hike

• Jr. Member
• Posts: 69
Re: Nested procedures
« Reply #7 on: June 13, 2024, 10:59:40 pm »

Do you remember how in old fashioned Windows Batch language
you could use the "pipe" command "|" to direct the output of one command
into the input of the next command?

============
ECHO. |TIME
============

I wonder if the Pascal Gods would be angered if I tried to implement this
in Pascal just as an exercise (in frustration). I might try by using pointers
in some naughty way.

egsuh

• Hero Member
• Posts: 1396
Re: Nested procedures
« Reply #8 on: June 14, 2024, 04:11:50 am »

For names in seasons Do str(names, M1.Lines[M1.Lines.Add('')]);

BildatBoffin

• New Member
• Posts: 20
Re: Nested procedures
« Reply #9 on: June 14, 2024, 06:53:15 am »
I wonder if the Pascal Gods would be angered if I tried to implement this
in Pascal just as an exercise (in frustration). I might try by using pointers
in some naughty way.

Some languages call that https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax. The FPC equivalent for now is to define type helpers.
« Last Edit: June 14, 2024, 07:30:36 am by BildatBoffin »

• Hero Member
• Posts: 15210
• Censorship about opinions does not belong here.
Re: Nested procedures
« Reply #10 on: June 14, 2024, 07:38:35 am »
============
ECHO. |TIME
============
That is called function chaining and is already possible in object pascal.
two examples are:
- component create functions that return self (KOL works like that)
- pipes (that's how echo | time works )
Of course the national anthem of the U.S.A. was written by Jimi Hendrix, didn't you know that?

MarkMLl

• Hero Member
• Posts: 7120
Re: Nested procedures
« Reply #11 on: June 14, 2024, 08:50:52 am »
I wonder if the Pascal Gods would be angered if I tried to implement this
in Pascal just as an exercise (in frustration). I might try by using pointers
in some naughty way.

Should be easy enough with a couple of TProcesses, but will need a code fragment between them to transfer the data... you might be able to hook OnRunCommandEvent for that.

Otherwise just use the shell as the binary, as nature intended:

Code: Text  [Select][+][-]
1. /bin/sh -c "echo -n C`svnversion -n`C |tr A-G %-+ >project_svnrevision.inc & echo -n C`svnversion -n \$FPCSrcDir()`C |tr A-G %-+>fpc_svnrevision.inc"
2.

That's something that I routinely use before Lazarus builds a project, and the IDE passes that more or less directly to a TProcess. As you can see, it exercises shell syntax fairly thoroughly, together with path resolution etc.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

VisualLab

• Sr. Member
• Posts: 391
Re: Nested procedures
« Reply #12 on: June 14, 2024, 10:23:51 am »
We can not yet write a restriction like str<T:ordinal> but it is considered to be implemented. Once it is, this code would be very safe.
I show this, because this new feature of implicit specialization is very powerful and I recently started to use it a lot. (but I don't have to write production code anymore.....)

Have I understood correctly that it will be possible to use constraints on generic types? (e.g.: ordinal, enumeration, numeric?) Will there be constraints for numeric types too? (e.g.: integer, real?)

• Hero Member
• Posts: 15210
• Censorship about opinions does not belong here.
Re: Nested procedures
« Reply #13 on: June 14, 2024, 11:36:29 am »
Numeric types sec are ordinals (of course not float types)
We already have constraints for classes and records.
My outstanding  feature request is about just ordinals, which includes by their very nature all integer types and enumerations. It is well received.
So where we can now already limit a generic to a class or record, we would be able to write somegeneric<T:Ordinal> which makes it type safe for any type that can be expressed as an ordinal.
Quote
(e.g.: ordinal, enumeration, numeric?)
All of these fall in the category ordinal. It would be the specialization that determines what kind of ordinal, just as with class and record restrictions.

I have not thought about a float restriction. I see less use for it. Floats have only one typekind, just tkFloat, which can easily be handled by overloads. Ordinal values have multiple typekinds. See:
https://www.freepascal.org/docs-html/rtl/system/ttypekind.html

Although in both cases you can already do things like this:
Code: Pascal  [Select][+][-]
1. generic function testme<T>(const value:T):T;
2. begin
3.   Assert(GetTypeKind(value)= tkFloat,'is not a float');
4.   //work with T
5. end;
« Last Edit: June 14, 2024, 05:42:39 pm by Thaddy »
Of course the national anthem of the U.S.A. was written by Jimi Hendrix, didn't you know that?