Re: How do I print a structure?
[email protected] (ToddAndMargo via perl6-users) Sat, 12 Apr 2025 11:56:07 -0700
| Newsgroups | perl.perl6.users |
|---|---|
| Message-ID | <[email protected]> |
On 4/12/25 10:14 AM, Tirifto wrote:
> Hello!
>
> Both `print` and `say` convert their argument to a string, but they do
> so by calling different methods on the argument. `print` calls the
> method `.Str`, while `say` calls the method `.gist`. On custom classes
> (like your PartitionClass), calling `.Str` will only return the object’s
> identifier by default, but calling `.gist` (or `.raku`) will return code
> you can run to re-create the object. So to get the same output with
> `print` like you did with `say`, only without the newline, you can do
> `print $Partition.gist` or `print $Partition.raku`. (`.gist` might not
> show the entire code if the text gets too long, so you might prefer to
> use `.raku`.)
>
> Calling `.kv` doesn’t work, because objects (/unlike/ maps / tables)
> aren’t transparent structures that you can see the insides of. From the
> perspective of OOP, objects are opaque, and the only proper way to look
> inside is by calling their methods. So if you want to be able to see all
> of the object’s attributes, you should *give the class a method* that
> will return all of the object’s attributes in some form. You could
> override the `.Str` or `.gist` methods if you simply want to print the
> attributes in a nice form, or you could override the `.kv` method if you
> might want to do something else with them. Here’s an example:
>
> [0] > class PartitionClass{
> has Str $.DeviceID is rw;
> has Str $.VolumeName is rw;
> has Str $.ProviderName is rw;
> has Str $.UNC_BackupPath is rw;
> has Int $.DriveType is rw;
> has Str $.DriveTypeStr is rw;
> has Int $.FreeSpace is rw;
> has Int $.Size is rw;
> has Int $.PercentUsed is rw;
> has Int $.PercentRemaining is rw;
>
> #| Return a list of pair objects: (Attribute name => Attribute
> value)
> method pairs(--> Iterable) {
> :$.DeviceID, :$.VolumeName, :$.ProviderName,
> :$.UNC_BackupPath, :$.DriveType, :$.DriveTypeStr,
> :$.FreeSpace, :$.Size, :$.PercentUsed, :$.PercentRemaining;
> }
>
> #| Return a sequence of attribute names and values interleaved.
> method kv(--> Iterable) {
> $.pairs.map({ .kv }).flat;
> }
>
> #| Return a string presenting all attributes on a single line.
> method Str(--> Str) {
> $.pairs.map({ .key ~ “: ” ~ .value }).join(“, ”) ~ “.”;
> }
> }
> (PartitionClass)
>
> [1] > my $Partition = PartitionClass.new(
> DeviceID => "",
> VolumeName => "",
> ProviderName => "",
> UNC_BackupPath => "",
> DriveType => 0,
> DriveTypeStr => "Unknown",
> FreeSpace => 0,
> Size => 0,
> PercentUsed => 0,
> PercentRemaining => 100
> );
> PartitionClass.new(DeviceID => "", VolumeName => "", ProviderName =>
> "", UNC_BackupPath => "", DriveType => 0, DriveTypeStr => "Unknown",
> FreeSpace => 0, Size =>
> 0, PercentUsed => 0, PercentRemaining => 100)
>
> [2] > for $Partition.kv -> $i, $j { print "i <$i> j <$j>\n" }
> i <DeviceID> j <>
> i <VolumeName> j <>
> i <ProviderName> j <>
> i <UNC_BackupPath> j <>
> i <DriveType> j <0>
> i <DriveTypeStr> j <Unknown>
> i <FreeSpace> j <0>
> i <Size> j <0>
> i <PercentUsed> j <0>
> i <PercentRemaining> j <100>
>
> [2] > print $Partition ~ "\n";
> DeviceID: , VolumeName: , ProviderName: , UNC_BackupPath: ,
> DriveType: 0, DriveTypeStr: Unknown, FreeSpace: 0, Size: 0,
> PercentUsed: 0, PercentRemaining: 100.
>
> [2] > say $Partition;
> PartitionClass.new(DeviceID => "", VolumeName => "", ProviderName =>
> "", UNC_BackupPath => "", DriveType => 0, DriveTypeStr => "Unknown",
> FreeSpace => 0, Size =>
> 0, PercentUsed => 0, PercentRemaining => 100)
>
> Of course, both the code and the formatting of the output could be
> improved. :-)
>
> You could also ask Raku to list all of the object’s attributes and then
> find each of their values for your object. This pretty much violates the
> principles of OOP, so it might not be something you want your programs
> to rely on, but if you just need to inspect an object’s internal state
> for your personal use, it’s probably fine! An example:
>
> [2] > for $Partition.^attributes { say “{.name}: {.get_value:
> $Partition}” }
> $!DeviceID:
> $!VolumeName:
> $!ProviderName:
> $!UNC_BackupPath:
> $!DriveType: 0
> $!DriveTypeStr: Unknown
> $!FreeSpace: 0
> $!Size: 0
> $!PercentUsed: 0
> $!PercentRemaining: 100
>
> If there are better ways, I’m afraid I don’t know of them. Hope this
> helps, though! ^ ^
> // Tirifto
>
> On 11. 04. 25 8:19, ToddAndMargo via perl6-users wrote:
>> Hi All,
>>
>> I am not having any luck printing the values of a OOP
>> structure, except for printing them one at a time. I
>> can get it to messily print with `say`, but I want to
>> do it with `print` so I can control the line feeds,
>> comments, etc..
>>
>> What am I doing wrong?
>>
>> Many thanks,
>> -T
>>
>>
>> [0] > class PartitionClass{
>> has Str $.DeviceID is rw;
>> has Str $.VolumeName is rw;
>> has Str $.ProviderName is rw;
>> has Str $.UNC_BackupPath is rw;
>> has Int $.DriveType is rw;
>> has Str $.DriveTypeStr is rw;
>> has Int $.FreeSpace is rw;
>> has Int $.Size is rw;
>> has Int $.PercentUsed is rw;
>> has Int $.PercentRemaining is rw;
>> }
>> (PartitionClass)
>>
>>
>> [1] > my $Partition = PartitionClass.new(
>> DeviceID => "",
>> VolumeName => "",
>> ProviderName => "",
>> UNC_BackupPath => "",
>> DriveType => 0,
>> DriveTypeStr => "Unknown",
>> FreeSpace => 0,
>> Size => 0,
>> PercentUsed => 0,
>> PercentRemaining => 100
>> );
>> PartitionClass.new(DeviceID => "", VolumeName => "", ProviderName =>
>> "", UNC_BackupPath => "", DriveType => 0, DriveTypeStr => "Unknown",
>> FreeSpace => 0, Size => 0, PercentUsed => 0, PercentRemaining => 100)
>>
>>
>> [2] > for $Partition.kv -> $i, $j { print "i <$i> j <$j>\n" }
>> i <0> j <PartitionClass<4875316684000>>
>>
>>
>> [2] > print $Partition ~ "\n";
>> PartitionClass<4875316684000>
>>
>>
>> [2] > say $Partition;
>> PartitionClass.new(DeviceID => "", VolumeName => "", ProviderName =>
>> "", UNC_BackupPath => "", DriveType => 0, DriveTypeStr => "Unknown",
>> FreeSpace => 0, Size => 0, PercentUsed => 0, PercentRemaining => 100)
>>
Hi Tirifto,
What a ton of work you put into that response. Very,
very much appreciated!
And yes, it does help. I will be copying your response
down into my keepers.
LOVE oop's!
-T