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)