Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #1083 (closed enhancement: wontfix)

Opened 16 years ago

Last modified 16 years ago

Outputting structs and objects can be done more cleanly

Reported by: schveiguy Assigned to: kris
Priority: normal Milestone: 2.0
Component: IO Version:
Keywords: triage Cc: larsivi

Description

Currently, Stdout(myObject) is equivalent to Stdout(myObject.toString).

However, this sometimes is not optimal. For instance, a user may want to output all the elements that a collection class contains. But if toString always concatenated together string representations of all the elements, this would be a heap allocation nightmare, for something that is going to live for about a microsecond.

What would be nicer is a way to ask the object to output itself to a stream, which would fit rather nicely into the stream model. You could even provide formatting arguments to the object (such as only output the size and type of a collection).

There are two ways to achieve this goal. One is to allow Layout to be extendable. Basically, you could add hooks into layout that triggered when a certain class type was outputted. This also might be the only way to have structs that can be outputted, as the typeinfo doesn't say at runtime whether just any function is implemented in a struct (toString is special and the compiler does fill in a typeinfo member for that).

The second way is to define an interface, e.g.:

interface Printable
{
  OutputStream print(OutputStream os);
  OutputStream print(OutputStream os, char[] format);
}

The format version would be called if the {} had arguments in it.

I think both options should be implemented to allow one to customize output in a way that the original object designer may not have thought of. And like I said earlier, structs can't implement interfaces, so some external function will have to be the one to output it. Perhaps the struct output function could be registered in a static this()?

Not sure if this has been proposed before, but I couldn't find anything on the ticket system.

Change History

05/02/08 07:59:15 changed by kris

  • status changed from new to assigned.

we discussed various ways to handle this with Walter at the conference last year. Nothing really came of that, though the notions discussed bear some similarity. We also asked for the D2 structs to support interfaces in a way that would make them fully usable in such a scenario. No word on that.

Also, the Mango Stdio was based upon Reader/Writer and thus had support for IReadable and IWritable interfaces for just this kind of reason. Without support for struct-based interfaces, a workaround using delegates was applied.

Either way, what you discuss is the type of thing Tango already does internally, where a callback is often provided in order to consume output directly into an output stream or buffer (as opposed to generating on the heap first).

My preferred approach would be for D2 structs to support interfaces, in a usable manner. One alternative is to support a 'producer' delegate as an Stdout argument, which works for classes, structs, and everything else too.

(follow-up: ↓ 3 ) 05/02/08 08:01:40 changed by kris

make that a lazy delegate ...

(in reply to: ↑ 2 ) 05/02/08 21:20:20 changed by schveiguy

Any solution is fine, as long as I can have an object or struct x, and do:

Stdout(x);

And this doesn't build a giant string that is output to Stdout and then thrown away :)

Struct interfaces sounds like the way to go. I've always wondered if struct interfaces would be possible. I can't think of a reason why they shouldn't be, since structs cannot inherit, the interface list can be stored in the typeinfo. Is there an official enhancement request for this on bugzilla?

Another compromise solution to request from Walter & Co. would be to have the compiler examine the compiled version of TypeInfo_Struct to see if there are any custom 'interface' functions it can fill in. For example, currently if a toString method is present in a struct, the TypeInfo_Struct.xtoString member is filled out (by the compiler?) to point to that method. It would be nice if the compiler saw xfoo as a delegate member in the TypeInfo_Struct class definition, and a struct had a method foo which matched the delegate signature, it would point the delegate at it. Maybe this can be done already (I'm not sure who's responsible for that). In that case, you COULD have essentially a global 'interface', kind of like all objects have a toString, all structs could have a pointer to their 'print' function.

05/25/08 14:11:29 changed by larsivi

  • keywords set to triage.

06/10/08 15:53:26 changed by kris

  • status changed from assigned to closed.
  • resolution set to wontfix.

language level request