fireartist has asked for the wisdom of the Perl Monks concerning the following question:

I've written a package that I'm using to return dates formatted for my application.
I'm just in the beginnings of learning to write OO, and I don't understand this behaviour.
I would most appreciate it if someone could explain where I'm going wrong.

I if run this (using the package below)
#!/usr/bin/perl -wT use strict; my $d = data->new; print $d->Y, "\n";
I get the expected result
2002
However, if I run
#!/usr/bin/perl -wT use strict; my $d = data->new; print "$d->Y\n";
I get the following result
data=HASH(0x254c7228)->Y
My understanding is that this is printing the reference, rather than the referant I want, but I don't know why.
{ package data; ######################### # Call a new package with # my $d = data->new; # # Use this on other dates (than localtime) # by calling a new package with the date # my $d = data->('YYYY-MM-DD hh:mm:ss'); # or # my $d = data->('YYYYMMDDhhmmss'); # # switch on 'nice' dates with # $d->nice(1); # and switch it back off with # $d->nice(0); ########################## sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; if (my $input = shift) { if ($input =~ /^(\d{4})-?(\d{2})-?(\d{2}) ?(\d{2}):?(\d{2}):?(\d{2 +})$/) { $self->{year} = $1; $self->{month} = $2; $self->{day} = $3; $self->{hour} = $4; $self->{minute} = $5; $self->{second} = $6; } } else { my @datetime = localtime(); $datetime[0] += 1; #format the seconds $datetime[4] += 1; #format the month $datetime[5] += 1900; #format the year $self->{second} = $datetime[0]; $self->{minute} = $datetime[1]; $self->{hour} = $datetime[2]; $self->{day} = $datetime[3]; $self->{month} = $datetime[4]; $self->{year} = $datetime[5]; } $self->{nice} = '0'; bless ($self, $class); return $self; } sub nice { my $self = shift; my $value = shift; if ($value == 1) { $self->{nice} = 1; } elsif ($value == 0) { $self->{nice} = 0; } } sub s { my $self = shift; return $self->{second}; } sub m { my $self = shift; return $self->{minute}; } sub h { my $self = shift; return $self->{hour}; } sub D { my $self = shift; if ($self->{nice} == 1) { my $value = $self->{day}; if ($value == 1) { "1st" } elsif ($value == 2) { "2nd" } elsif ($value == 3) { "3rd" } elsif ($value == 21) { "21st" } elsif ($value == 22) { "22nd" } elsif ($value == 23) { "23rd" } elsif ($value == 31) { "31st" } elsif (($value >= 4) && ($value <= 31)) { return $value . "th"; } } else { return $self->{day}; } } sub M { my $self = shift; if ($self->{nice} == 1) { my $value = $self->{month}; if ($value == 1) { "January" } elsif ($value == 2) { "February" } elsif ($value == 3) { "March" } elsif ($value == 4) { "April" } elsif ($value == 5) { "May" } elsif ($value == 6) { "June" } elsif ($value == 7) { "July" } elsif ($value == 8) { "August" } elsif ($value == 9) { "September" } elsif ($value == 10) { "October" } elsif ($value == 11) { "November" } elsif ($value == 12) { "December" } else { "invalid month" } } else { return $self->{month}; } } sub Y { my $self = shift; return $self->{year}; } }

Replies are listed 'Best First'.
Re: printing a package result within quotes
by broquaint (Abbot) on May 17, 2002 at 14:02 UTC
    This is because methods aren't interpolated within strings. There are various tricks to get around this but they're usually used only within the context of golfing, obfu or job security situations e.g
    my $f = sub { return 'a sub' }; print "\$f is ${\$f->()}\n"; __output__ $f is a sub
    As you can see this is not very nice, so I'd go with these friendler solutions
    my $f = sub { return 'a sub' }; # list print "\$f is ", $f->(), "\n"; # concat print "\$f is ". $f->(). "\n"; # save return my $ret = $f->(); print "\$f is $ret\n";

    HTH

    _________
    broquaint

    update: removed initial example as it could be confusing

Re: printing a package result within quotes
by Joost (Canon) on May 17, 2002 at 14:04 UTC
    Method calls will not normally be interpolated in a ""-string. You can use this:
    my $d = data->new; print $d->Y, "\n"; # call $d->Y() in list context
    or
    my $d = data->new; print $d->Y()."\n"; # call $d->Y() in scalar context
    or use the infernally ugly and difficult to remember:
    my $d = data->new; print "@{[ $d->Y ]}\n"; # can't remember if this # is in scalar or list context :-)
    -- Joost downtime n. The period during which a system is error-free and immune from user input.
Re: printing a package result within quotes
by jmcnamara (Monsignor) on May 17, 2002 at 14:07 UTC

    Perl will interpolate $d but not the entire method $d->Y

    If that is really what you need to do then you could try the following inelegant construction:     print "@{[$d->Y]}";

    However, it would be better to just store the return value of the method in a scalar and then interpolate that in a string.

    --
    John.