Recent

Author Topic: Feature request: writeln(ClassInstance)  (Read 1519 times)

JdeHaan

  • Full Member
  • ***
  • Posts: 170
Feature request: writeln(ClassInstance)
« on: October 08, 2025, 06:08:10 pm »
Hi,

I have a number of classes and each has an overridden toString method.
I was just thinking that it would be great if I could just use

Code: Pascal  [Select][+][-]
  1. writeln(ClassInstance);

and the toString method is automatically called.
Since TObject is the base class of all classes, and comes with a toString method, this should work for all class instances, right?
And when the Instance is Nil, the write 'nil'.

Currently, an error is generated by the compiler if you try to writeln the class instance.


Lazarus + FPC trunk; MacOs Tahoe

« Last Edit: October 08, 2025, 06:13:12 pm by JdeHaan »

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Feature request: writeln(ClassInstance)
« Reply #1 on: October 08, 2025, 07:03:25 pm »
a. leads to code bloat, needs Tpersistent descendant because of RTTI that is necessary.
b. fpc is not a scripting language.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

wp

  • Hero Member
  • *****
  • Posts: 13222
Re: Feature request: writeln(ClassInstance)
« Reply #2 on: October 08, 2025, 07:34:49 pm »
Great - I did not know of the class.ToString... But what is the issue in writing this explicitely?
Code: Pascal  [Select][+][-]
  1.   WriteLn(ClassInstance.ToString);

JdeHaan

  • Full Member
  • ***
  • Posts: 170
Re: Feature request: writeln(ClassInstance)
« Reply #3 on: October 08, 2025, 08:01:38 pm »
It's not really an issue, and I use WriteLn(Instance.toString) all the time. However, the writeln proc is already smart in writing values of all types of variables, so why not add a class instance to the logic as well, since an instance always has a toString method.

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Feature request: writeln(ClassInstance)
« Reply #4 on: October 08, 2025, 08:08:02 pm »
Except that the instance name never shows up in the generated assembler. That will only work if RTTI is generated.
That is usually not good for code speed and size. FPC is not a scripting language.
Does not mean it is not possible: it can be done using RTTI and it is even not difficult, only cumbersome.
And you need Tpersistent as root class, not Tobject. E.g. custom attributes rely on that.
Tobject.tostring returns class name, not instance name....Instance name requires more.
« Last Edit: October 08, 2025, 08:22:18 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12536
  • FPC developer.
Re: Feature request: writeln(ClassInstance)
« Reply #5 on: October 08, 2025, 08:31:34 pm »
a. leads to code bloat, needs Tpersistent descendant because of RTTI that is necessary.
b. fpc is not a scripting language.

It does not. Tostring is a virtual method of tobject. The implementation of certain classes might use RTTI, but that is not mandatory

Still, I think  it is a bit over the top. A language feature is a big thing, and the use of this is so, so limited.

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Feature request: writeln(ClassInstance)
« Reply #6 on: October 08, 2025, 08:40:23 pm »

It does not.
It does by default. And yes it is virtual, so if there is RTTI generated it can also return the instance name:scripting.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11826
  • Debugger - SynEdit - and more
    • wiki
Re: Feature request: writeln(ClassInstance)
« Reply #7 on: October 08, 2025, 08:58:42 pm »
Except that the instance name never shows up in the generated assembler. That will only work if RTTI is generated.
Quote
And you need Tpersistent as root class, not Tobject.

Not that anyone mentioned "instancename" before you... And also not sure why (or what) you mean by it.

"TObject.ToString" prints the ClassName.

And that works without needing TPersistent. At least the code below prints "TObject" (which happens to be the classname)

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. var a:TObject;
  3. begin
  4.   a:= TObject.Create;
  5.   writeln(a.ToString);
  6. end.




As for the original question...

Maybe try a custom
Code: Pascal  [Select][+][-]
  1.    operator := (a:TObject): string;

I have no idea if it will work for this case. But similar operators work for passing parameters to functions, when and if those function have explicit typed params (as normal function usually do / but writeln kinda takes more...)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12536
  • FPC developer.
Re: Feature request: writeln(ClassInstance)
« Reply #8 on: October 08, 2025, 08:58:56 pm »

It does not.
It does by default.

Code: Pascal  [Select][+][-]
  1.       function TObject.ToString: RTLString;
  2.         begin
  3.           result:=ClassName;
  4.         end;
  5.  


Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Feature request: writeln(ClassInstance)
« Reply #9 on: October 08, 2025, 09:07:34 pm »
Not that anyone mentioned "instancename" before you... And also not sure
You seem to have mis-read the original question which explicitly is about instance, not class.
TButton <> Button1
« Last Edit: October 08, 2025, 09:11:02 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11826
  • Debugger - SynEdit - and more
    • wiki
Re: Feature request: writeln(ClassInstance)
« Reply #10 on: October 08, 2025, 09:14:20 pm »
Not that anyone mentioned "instancename" before you... And also not sure
You seem to have mis-read the original question which explicitly is about instance, not class.
TButton <> Button1

The original just ask to print whatever the "ToString" prints for the instance. => ToString prints the classname. (but he may want his overwritten one to be called...).

He does not mention "instance name".

Btw, "a" in my example is an instance, just as he demanded. (but of course explicitly needs the ToString call, just as he does not want)

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Feature request: writeln(ClassInstance)
« Reply #11 on: October 09, 2025, 06:58:25 am »
In trunk something like this is already possible:
Code: Pascal  [Select][+][-]
  1. program inv;
  2. {$ifdef fpc}{$mode delphi}{$endif}{$H+}
  3. {$apptype console}
  4. uses
  5.   classes;
  6. type
  7.   { A reference is a refcounted interface with invoke method}
  8.    INameProc = reference to function:string;
  9.    
  10.    TMyObject = class(TInterfacedObject,INameproc)
  11.    public
  12.      function invoke:string;
  13.    end;
  14.  
  15. function TMyObject.invoke:string;
  16. begin
  17.   Result := ToString;
  18. end;  
  19.  
  20. var
  21.   a:INameProc;
  22. begin
  23.   a := TMyObject.Create {$ifndef fpc}as INameProc{$endif};  // as just for Delphi
  24.   writeln(a()); // calls invoke
  25.   readln;
  26. end.
But that requires to derive from TInterfacedObject.
There is a slight incompatibility with Delphi 12+, where you don't need the brackets. writeln(a);
OTOH, fpc does not need as INameProc;
The above code compiles in both.
Hey, presto, writeln accepts objects  :D
« Last Edit: October 09, 2025, 03:41:46 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11826
  • Debugger - SynEdit - and more
    • wiki
Re: Feature request: writeln(ClassInstance)
« Reply #12 on: October 09, 2025, 08:46:07 am »
Just to follow up my earlier idea. The operator trick doesn't seem to work. I guess because "writeln" accepts some sort of variant-ish type, rather than string.

If you have a function "Bar(param: string);" that really wants a string, then you can use an operator, and pass an object. And the operator can call toString (or anything).

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. type
  3.   TFoo = class
  4.     function ToString: ansistring; override;
  5.   end;
  6.  
  7. function TFoo.ToString: ansistring;
  8. begin
  9.   Result := inherited ToString;
  10.   Result := Result + 'abc';
  11. end;
  12.  
  13. operator:= (x: TObject): string;
  14. begin
  15.   result := x.ToString;
  16. end;
  17.  
  18. procedure Bar(param: string);
  19. begin
  20.   writeln(param);
  21. end;
  22.  
  23. var
  24.   a,b: TObject;
  25.   c: TFoo;
  26. begin
  27.   a := TObject.Create;
  28.   b := TFoo.Create;
  29.   c := TFoo.Create;
  30.  
  31.   bar(a);
  32.   bar(b);
  33.   bar(c);
  34.   //WriteLn(a,b,c);
  35.   WriteLn(string(a),string(b),string(c));
  36. end.
  37.  

For writeln you need to cast the objects, but then you can also call ToString.
If you cast, you can probably also use the "explicit" operator. But I haven't tried that.

Thaddy

  • Hero Member
  • *****
  • Posts: 18364
  • Here stood a man who saw the Elbe and jumped it.
Re: Feature request: writeln(ClassInstance)
« Reply #13 on: October 09, 2025, 10:38:08 am »
Yes, but isn't his wish to have the notation shortened? A cast is the same as - basically - toString.
Your code is working, of course, but I think my ref solution comes closer to what he means.
Of course I just consider it - including my contribution - silly games with what the language allows. (And a not so smart FR, given what the compiler needs to add in otherwise useless code size, as I already explained: such a string needs to be stored and that goes for all solutions)
« Last Edit: October 09, 2025, 10:44:42 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6195
  • Compiler Developer
Re: Feature request: writeln(ClassInstance)
« Reply #14 on: October 09, 2025, 09:31:13 pm »
I have a number of classes and each has an overridden toString method.
I was just thinking that it would be great if I could just use

Code: Pascal  [Select][+][-]
  1. writeln(ClassInstance);

and the toString method is automatically called.
Since TObject is the base class of all classes, and comes with a toString method, this should work for all class instances, right?
And when the Instance is Nil, the write 'nil'.

The compiler doesn't need to babysit the user for each and everything. Just use ClassInstance.ToString and it will be clear even much later what you intended. And advantage: it works right now.

Just to follow up my earlier idea. The operator trick doesn't seem to work. I guess because "writeln" accepts some sort of variant-ish type, rather than string.

The comparison is simply wrong. Write is not a function, the compiler explicitly retrieve the passed in values and works on them directly to build up the list of function calls that make up the Write.

 

TinyPortal © 2005-2018