Recent

Author Topic: Nested procedures  (Read 2074 times)

Ten_Mile_Hike

  • Jr. Member
  • **
  • Posts: 88
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);
  10.     M1.lines.Add(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;  
When any government, or any church for that matter, undertakes to say to its subjects, This you may not read, this you
must not see, this you are forbidden to know, the end result is tyranny and oppression no matter how holy the motives.

Robert A. Heinlein

Fibonacci

  • Hero Member
  • *****
  • Posts: 615
  • 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: 88
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 »
When any government, or any church for that matter, undertakes to say to its subjects, This you may not read, this you
must not see, this you are forbidden to know, the end result is tyranny and oppression no matter how holy the motives.

Robert A. Heinlein

Fibonacci

  • Hero Member
  • *****
  • Posts: 615
  • 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: 1494
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).


Thaddy

  • Hero Member
  • *****
  • Posts: 16201
  • 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 »
If I smell bad code it usually is bad code and that includes my own code.

Thaddy

  • Hero Member
  • *****
  • Posts: 16201
  • 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 »
If I smell bad code it usually is bad code and that includes my own code.

Ten_Mile_Hike

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

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.
When any government, or any church for that matter, undertakes to say to its subjects, This you may not read, this you
must not see, this you are forbidden to know, the end result is tyranny and oppression no matter how holy the motives.

Robert A. Heinlein

egsuh

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

Hmmmm.. please try following...

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

BildatBoffin

  • New Member
  • *
  • Posts: 30
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 »

Thaddy

  • Hero Member
  • *****
  • Posts: 16201
  • 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 )
If I smell bad code it usually is bad code and that includes my own code.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8044
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.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

VisualLab

  • Hero Member
  • *****
  • Posts: 577
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?)

Thaddy

  • Hero Member
  • *****
  • Posts: 16201
  • 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 »
If I smell bad code it usually is bad code and that includes my own code.

 

TinyPortal © 2005-2018