Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Objects/Structures in Perl

Reply
Thread Tools

Objects/Structures in Perl

 
 
O. Olson
Guest
Posts: n/a
 
      07-26-2007
Hi,
I am for most part familiar C++/Java programming - but not much with
Perl. I am trying to figure out if I can use C style structures in
Perl - they are not classes per se - but sort of similar.

In the following code - which is part of a larger program - I tried
to group the hours, minutes and seconds of time into a combined data
structure. However once I set the current time ($curr_time) - the next
midnight time ($next_midnight) gets changed. Can anyone guess why??

As I said I am not much into Perl - so I might be doing something
obviously wrong.

-------------------------------------------------------------------
use warnings;
use strict;

# Declaration of a data structure that would hold a single line or
record of the file
# This would ensure that the file would never remain open if the
program exits prematurely

my $time = {
HOUR => my $hour,
MINUTE => my $minute,
SECOND => my $second
};

# Defining two variables of the type time
my $curr_time = $time; #Contains the hour, minute, second
my $next_midnight = $time; #Contains the hour, minute, second

# Setting the Next Midnight Time
($next_midnight->{HOUR}, $next_midnight->{MINUTE}, $next_midnight-
>{SECOND}) = (23, 59, 5;

print "Next Midnight Time: "; &printTime($next_midnight); print "\n";

# Setting the current time
($curr_time->{SECOND}, $curr_time->{MINUTE}, $curr_time->{HOUR}) =
localtime();
print "curr_time Time: "; &printTime($curr_time); print "\n";
print "But now, Next Midnight Time: "; &printTime($next_midnight);
print "\n";


# This function would print the time variable passed on to it, without
adding a new line character to it
sub printTime()
{
# Declaring a temporary time variable
my $temp_time = $time;
$temp_time = $_[0];
print "$temp_time->{HOUR}:$temp_time->{MINUTE}:$temp_time-
>{SECOND}";

}

------------------------------------------------------------
Console Output:
Next Midnight Time: 23:59:58
curr_time Time: 22:50:12
But now, Next Midnight Time: 22:50:12
---------------------------------------------------------

Why did "Next Midnight Time" change?

Thanks to all who help,
O.O.

 
Reply With Quote
 
 
 
 
Tad McClellan
Guest
Posts: n/a
 
      07-26-2007
O. Olson <> wrote:

> I am trying to figure out if I can use C style structures in
> Perl



perldoc -q struct

How can I make the Perl equivalent of a C structure/C++ class/hash or
array of hashes or arrays?


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
 
Reply With Quote
 
 
 
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      07-27-2007
O. Olson <> wrote:
> I am for most part familiar C++/Java programming - but not much with
> Perl. I am trying to figure out if I can use C style structures in
> Perl - they are not classes per se - but sort of similar.


There's the one problem that Perl is neither C++ (or C) nor Java and
it doesn't have C style structures...

> In the following code - which is part of a larger program - I tried
> to group the hours, minutes and seconds of time into a combined data
> structure. However once I set the current time ($curr_time) - the next
> midnight time ($next_midnight) gets changed. Can anyone guess why??


> As I said I am not much into Perl - so I might be doing something
> obviously wrong.


> -------------------------------------------------------------------
> use warnings;
> use strict;


> # Declaration of a data structure that would hold a single line or
> record of the file
> # This would ensure that the file would never remain open if the
> program exits prematurely


> my $time = {
> HOUR => my $hour,
> MINUTE => my $minute,
> SECOND => my $second
> };


> # Defining two variables of the type time
> my $curr_time = $time; #Contains the hour, minute, second
> my $next_midnight = $time; #Contains the hour, minute, second


> # Setting the Next Midnight Time
> ($next_midnight->{HOUR}, $next_midnight->{MINUTE}, $next_midnight-
> >{SECOND}) = (23, 59, 5;

> print "Next Midnight Time: "; &printTime($next_midnight); print "\n";


> # Setting the current time
> ($curr_time->{SECOND}, $curr_time->{MINUTE}, $curr_time->{HOUR}) =
> localtime();
> print "curr_time Time: "; &printTime($curr_time); print "\n";
> print "But now, Next Midnight Time: "; &printTime($next_midnight);
> print "\n";



> # This function would print the time variable passed on to it, without
> adding a new line character to it
> sub printTime()
> {
> # Declaring a temporary time variable
> my $temp_time = $time;
> $temp_time = $_[0];
> print "$temp_time->{HOUR}:$temp_time->{MINUTE}:$temp_time-
> >{SECOND}";

> }


> ------------------------------------------------------------
> Console Output:
> Next Midnight Time: 23:59:58
> curr_time Time: 22:50:12
> But now, Next Midnight Time: 22:50:12
> ---------------------------------------------------------


> Why did "Next Midnight Time" change?


I can't answer this queston - my question is how you did get that
output at all since (for several reasons) your above code isn't
valid Perl?

I guess you need to free yourself at least a bit of your C++/Java
background and use instead what Perl gives you. While there are
many ways to do it, my first approach would probably be to create a
package for times like the following (with a bit of code at the start
that uses the package and outputs something similar to what you
posted):

------8<-------------------------------------------------------#!/usr/bin/perl
#!/usr/bin/perl

use strict;
use warnings;

my $current_time = new MyTime( );
my $next_midnight = new $current_time( 23, 59, 58 );
print "Next Midnight Time: " . $next_midnight->as_text . "\n" .
"curr_time Time: " . $current_time->as_text . "\n",
"But now, Next Midnight Time: " . $next_midnight->as_text . "\n";


package MyTime;

=pod

=head1 METHODS

=over 4

=item new()

new() can be called with 0 to 3 arguments: if there is none the new
object is initialized to the current (local) time, otherwise the
first argument is taken to be the hour, the second to be the minute
and the third as the second. Missing arguments are assumed to be 0.

=cut

sub new {
my $inv = shift;
my $class = ref( $inv ) || $inv;
die "Too many arguments\n" unless @_ <=3;
my $self;
if ( @_ == 0 ) { # no arguments
my @time = localtime( );
$self = { hour => $time[ 2 ],
minute => $time[ 1 ],
second => $time[ 0 ] };
} else {
$self = { hour => $_[ 0 ],
minute => $_[ 1 ] || 0,
second => $_[ 2 ] || 0 };
}
return bless $self, $class;
}

=pod

=item as_text()

Returns a string of the time the object represents in "hh:mm:ss" format.

=cut

sub as_text {
my $self = shift;
return sprintf "%02d:%02d:%02d",
$self->{ hour }, $self->{ minute }, $self->{ second };
}

1;
------8<-------------------------------------------------------

That way you can create new objects (similar to C++ or Java)
representing times and print them. Adding methods that return
or change the hour, minute or second is simple, e.g. for getting
or setting the hour you would just need e.g.

sub hour {
my $self = shift;
$self->{ hour } = shift if exists $_[ 0 ];
return $self->{ hour };
}

Of course, this MyTime package would need quite a bit of error
checking (what happens when you pass it non-numeric or negative
arguments or hours above 23 or minutes or seconds above 59?)
but I hope it gives you an idea of how you could do it in Perl.

Regards, Jens
--
\ Jens Thoms Toerring ___
\__________________________ http://toerring.de
 
Reply With Quote
 
O. Olson
Guest
Posts: n/a
 
      07-27-2007
On Jul 26, 11:48 pm, Keith Keller <kkeller-use...@wombat.san-
francisco.ca.us> wrote:
>
> It's probably easier to simply create each hashref the way you want it:
>
> my $curr_time={
> HOUR => 1,
> MINUTE => 2,
> SECOND => 3,
>
> };
>
> my $next_midnight={
> HOUR => 4,
> MINUTE => 5,
> SECOND => 6,
>
> };
>


I don't think I can do this, because I am going to be using this as a
variable. I think I would try Jens solution below.

> Some more unrelated comments:
>
> > # This function would print the time variable passed on to it, without
> > adding a new line character to it
> > sub printTime()

>
> You have (), which strictly speaking defines printTime as a function
> that takes no arguments. You don't see any errors because calling it
> like you do above (&printTime($next_midnight)) circumvents prototypes.
> You should probably leave out both the () on the sub definition, and the
> & on function calls.
>


This is an interesting thing. I looked at "perlsub" - and though they
mention creating subroutines with prototypes - they do not elaborate
on it. For e.g. I tried:

sub printTime($temp_time)
{
print "$temp_time";
}

Assuming $temp_time is a scalar like an integer. The compiler
complains that $temp_time is not defined. In case I do something
like :

sub printTime(my $temp_time)
{
print "$temp_time";
}

I still get the same error. What am I doing wrong?

Thanks again,
O.O.

 
Reply With Quote
 
O. Olson
Guest
Posts: n/a
 
      07-27-2007
Dear Jens,

I this is exactly what I wanted. I searched again on Google - but I
could not get the method you suggest anywhere on the net. I think I
have understood it overall - but I have a few questions.

On Jul 27, 2:19 am, j...@toerring.de (Jens Thoms Toerring) wrote:
> I can't answer this queston - my question is how you did get that
> output at all since (for several reasons) your above code isn't
> valid Perl?
>


I am running this using ActiveState Perl 5.8.7.815 under Windows XP.
I tried rerunning my exact same code that I posted again - and it does
give the same/similar output to what I have posted above.

My Questions:

> package MyTime;
>


Can this package be declared in a separate file - I tried it - but it
would not work. I put this in a file called "MyTime.pl" and in the
original source file put "use main::MyTime;". This does not work.

> sub new {
> my $inv = shift;
> my $class = ref( $inv ) || $inv;
> die "Too many arguments\n" unless @_ <=3;
> my $self;
> if ( @_ == 0 ) { # no arguments
> my @time = localtime( );
> $self = { hour => $time[ 2 ],
> minute => $time[ 1 ],
> second => $time[ 0 ] };
> } else {
> $self = { hour => $_[ 0 ],
> minute => $_[ 1 ] || 0,
> second => $_[ 2 ] || 0 };
> }
> return bless $self, $class;
>
> }
>


I think I did not understand some of the aspects of this new()
function - though I liked the clever way you created a new hash
everytime a new object of the class is required. Keith above mentioned
that I should do this - but he did not elaborate that way you did it.

1. I think from the documentation that "shift" would decrease the size
of the array @_ by 1. So shouldn't that at the top be @_ <=2;

2. I think I did not understand what the second line does:

my $class = ref( $inv ) || $inv;


3. Is $time sort of an implicit variable. I looked at the "localtime"
function at http://perldoc.perl.org/functions/localtime.html and I
could not find any mention of it.

4. Finally I have no idea about:

return bless $self, $class;

I looked at http://perldoc.perl.org/functions/bless.html regarding
bless - but I did not understand how $class would refer to the current
package.

>
> 1;
> ------8<-------------------------------------------------------
>


I would also like to know if every file in Perl should end with a 1; -
I did not know this before - but only learnt about it when you used
it.


> Regards, Jens


Thanks a lot for your code I think that's exactly what I wanted.

vielen Danke,
O.O.


 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      07-27-2007
"O. Olson" <> wrote in news:1185558752.760041.195290@
57g2000hsv.googlegroups.com:

> On Jul 27, 2:19 am, j...@toerring.de (Jens Thoms Toerring) wrote:

....
>
> My Questions:
>
>> package MyTime;
>>

>
> Can this package be declared in a separate file - I tried it - but it
> would not work. I put this in a file called "MyTime.pl" and in the
> original source file put "use main::MyTime;". This does not work.


Of course it can be put in a different file but there are rules that
determine where the resulting file goes.

See the section "Perl Modules" in perldoc perlmod.

Second, if the package is called MyTime then the package is called
MyTime not main::MyTime.

I fact, I would prefer not to put packages in the root namespace but
instead adopt the following convention:

package My::Time;

To use this package, suppose your application is in

C:\opt\mytime

I would then put my custom package in c:\opt\mytime\lib\My\Time.pm

That file would start with the package declaration:

package My::Time;

The application, let's assume the executable is mytime.pl, can then
specify the custom location:

#!/usr/bin/perl

use strict;
use warnings;

use File::Spec::Functions qw( catfile );
use FindBin qw( $Bin );

use lib catfile( $Bin, 'lib' );

use My::Time;

my $time = My::Time->new;

# ...
# ...

__END__

>> sub new {
>> my $inv = shift;
>> my $class = ref( $inv ) || $inv;


There two schools of thought on being able to call new on the class and
the object. I subscribe to the camp that thinks this is unnecessary.

sub new {
my $class = shift;


>> die "Too many arguments\n" unless @_ <=3;
>> my $self;
>> if ( @_ == 0 ) { # no arguments
>> my @time = localtime( );
>> $self = { hour => $time[ 2 ],
>> minute => $time[ 1 ],
>> second => $time[ 0 ] };
>> } else {
>> $self = { hour => $_[ 0 ],
>> minute => $_[ 1 ] || 0,
>> second => $_[ 2 ] || 0 };
>> }
>> return bless $self, $class;
>>
>> }
>>

>
> I think I did not understand some of the aspects of this new()
> function - though I liked the clever way you created a new hash
> everytime a new object of the class is required. Keith above mentioned
> that I should do this - but he did not elaborate that way you did it.


Because you are supposed to read the documentation that comes with Perl.
On Windows, look in the ActiveState Perl program group. Follow the link
for HTML docs. At least, read the table of contents. See the topics on
object oriented programming and read them.

>
> 1. I think from the documentation that "shift" would decrease the size
> of the array @_ by 1. So shouldn't that at the top be @_ <=2;


Again, if you had read the documentation (e.g. perldoc perlobj) you
would have known that the first argument to a method (not a subroutine)
is the name of the class. Again, you can easily check this:

C:\Home\asu1\Src\test\t> cat t.pl
#!/usr/bin/perl

package My::Test;

use strict;
use warnings;

use Data:umper;

sub new {
print Dumper \@_;
}

package main;

use strict;
use warnings;

my $t = My::Test->new( qw(a bunch of arguments) );

__END__


C:\Home\asu1\Src\test\t> t
$VAR1 = [
'My::Test',
'a',
'bunch',
'of',
'arguments'
];


> 2. I think I did not understand what the second line does:
>
> my $class = ref( $inv ) || $inv;


Enables new to be called on an object rather than just the class so you
can do:

my $x = My::Time->new( qw( blah blah blah ) );

my $y = $x->new;

I really see no good reason to do this. It is too confusing for people
of limited telepathic abilities (such as myself) as it is not clear to
me what a method named 'new' should do when invoked on an object.

> 3. Is $time sort of an implicit variable. I looked at the "localtime"
> function at http://perldoc.perl.org/functions/localtime.html and I
> could not find any mention of it.


Ahem, I cannot see any variable called $time in Jens' code.

> 4. Finally I have no idea about:
>
> return bless $self, $class;
>
> I looked at http://perldoc.perl.org/functions/bless.html regarding
> bless - but I did not understand how $class would refer to the current
> package.


See above.

> I would also like to know if every file in Perl should end with a 1; -
> I did not know this before - but only learnt about it when you used
> it.


No. Every file use'd or require'd should return a true value.

Again, reading the relevant documentation that is installed on your
computer would have alerted you to this.

Sinan

>> Regards, Jens

>
> Thanks a lot for your code I think that's exactly what I wanted.


Yup, another dish of fish served.

Sinan



--
A. Sinan Unur <>
(remove .invalid and reverse each component for email address)
clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>

 
Reply With Quote
 
Jens Thoms Toerring
Guest
Posts: n/a
 
      07-27-2007
O. Olson <> wrote:
> My Questions:


> > package MyTime;


> Can this package be declared in a separate file - I tried it - but it
> would not work. I put this in a file called "MyTime.pl" and in the
> original source file put "use main::MyTime;". This does not work.


You need to name it 'MyTime.pm' since it's a module. And in the
file that uses it you just put 'use MyTime;', without the 'main::'
in front of it.

> > sub new {
> > my $inv = shift;
> > my $class = ref( $inv ) || $inv;
> > die "Too many arguments\n" unless @_ <=3;
> > my $self;
> > if ( @_ == 0 ) { # no arguments
> > my @time = localtime( );
> > $self = { hour => $time[ 2 ],
> > minute => $time[ 1 ],
> > second => $time[ 0 ] };
> > } else {
> > $self = { hour => $_[ 0 ],
> > minute => $_[ 1 ] || 0,
> > second => $_[ 2 ] || 0 };
> > }
> > return bless $self, $class;
> >
> > }
> >


> I think I did not understand some of the aspects of this new()
> function - though I liked the clever way you created a new hash
> everytime a new object of the class is required. Keith above mentioned
> that I should do this - but he did not elaborate that way you did it.


It's not "my" clever way, it's copied staight from the Camel
book, "Programming Perl"


> 1. I think from the documentation that "shift" would decrease the size
> of the array @_ by 1. So shouldn't that at the top be @_ <=2;


Actually, the new() methid gets called with up to 4 arguments,
the first one being either the name of the package or an
object of the class. When you write

my $a = new MyTime();

(the parenthesis after MyTime are redundant), then you pass
1 argument to the new() method, the name of the class. So,
after the shift, you still should have up to 3 remaining
arguments.

> 2. I think I did not understand what the second line does:


> my $class = ref( $inv ) || $inv;


Since new() is a methid it can be either called with the name
of the class or via an object of that class. The first way
is either

my $a = new MyTime;

or, more verbose,

my $a = MyTime::new( 'MyTime' );

In this case the argument is the name of the class, so it's
not a reference and calling ref() on it returns false. The
other way to call it is as a method (if you already have an
object of that class)

my $b = $a->new;

In this case the method receives the object as it's first
argument (that's basically the 'this' variable from C++)
and ref() returns the name of the class.

> 3. Is $time sort of an implicit variable.


No, @time is just a simple array that is used locally to this
function. There's nothing "magic" about it.

> I looked at the "localtime"
> function at http://perldoc.perl.org/functions/localtime.html and I
> could not find any mention of it.


localtime() returns an array, which gets assigned to @time.

> 4. Finally I have no idea about:


> return bless $self, $class;


That's what ties it all together. Up to this line $self was
just a simple reference to an anonymous hash. But we want
it to be a bit more, a real object, and that's what the
bless function makes out of it - it makes $self an object
of the class MyTime (and returns the new object which we
then return to the caller. Only because of this you can
use it later with all the object-oriented bells and wistles
like calling

my $string = $a->as_text;

If you would leave out the call of bless you would get a
error message like "Can't call method "new" on unblessed
reference".

> >
> > 1;
> > ------8<-------------------------------------------------------
> >


> I would also like to know if every file in Perl should end with a 1; -
> I did not know this before - but only learnt about it when you used
> it.


Yes, every package and module needs to end in '1;' (or something
else that indicates success, so e.g. '"a";' would also do).

Regards, Jens
--
\ Jens Thoms Toerring ___
\__________________________ http://toerring.de
 
Reply With Quote
 
O. Olson
Guest
Posts: n/a
 
      07-28-2007
Thanks Sinan.

I am not very familiar with Perl. I do not use it too often and when
I come back to it after some time I invariably forget a lot of stuff
that I had known before.

On Jul 27, 8:59 pm, "A. Sinan Unur" <1...@llenroc.ude.invalid> wrote:
>
> I fact, I would prefer not to put packages in the root namespace but
> instead adopt the following convention:
>
> package My::Time;
>
> To use this package, suppose your application is in
>
> C:\opt\mytime
>
> I would then put my custom package in c:\opt\mytime\lib\My\Time.pm
>
> That file would start with the package declaration:
>
> package My::Time;
>


Thanks for this suggestion. I am not yet a professional developer - so
I would simply go with 'MyTime.pm'.


> There two schools of thought on being able to call new on the class and
> the object. I subscribe to the camp that thinks this is unnecessary.
>
> sub new {
> my $class = shift;
>


I think I agree with you here - because that's how C++/Java do it. But
anyway that new concept by Perl is nice to know.

Thank you for your other comments. I think Jens post clarified my
other questions.

Regards,
O.O.


 
Reply With Quote
 
O. Olson
Guest
Posts: n/a
 
      07-28-2007
Dear Jens,

Thank you for all of your detailed explanations. I think I have got
everything to work now.

On Jul 27, 9:03 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
> It's not "my" clever way, it's copied staight from the Camel
> book, "Programming Perl"
>


I found this method described in perltoot - I don't know how I missed
this earlier.


> No, @time is just a simple array that is used locally to this
> function. There's nothing "magic" about it.
>


I overlooked the @time variable here. I don't know how this happened.

>
> That's what ties it all together. Up to this line $self was
> just a simple reference to an anonymous hash. But we want
> it to be a bit more, a real object, and that's what the
> bless function makes out of it - it makes $self an object
> of the class MyTime (and returns the new object which we
> then return to the caller. Only because of this you can
> use it later with all the object-oriented bells and wistles
> like calling
>
> my $string = $a->as_text;
>
> If you would leave out the call of bless you would get a
> error message like "Can't call method "new" on unblessed
> reference".
>


I am totally new to "bless" - this is the first time I would be using
it. Thanks for the explanation.


> > I would also like to know if every file in Perl should end with a 1; -
> > I did not know this before - but only learnt about it when you used
> > it.

>
> Yes, every package and module needs to end in '1;' (or something
> else that indicates success, so e.g. '"a";' would also do).



I did not know this. I would be using this from now on.


>
> Regards, Jens


I think I have some more questions regarding subroutines and OO
programming in Perl - but I think I would start a new thread for that
as it is a bit unrelated to my current thread.

vielen Danke,
O.O.






 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      07-28-2007
"O. Olson" <> wrote in news:1185641646.800620.217700
@b79g2000hse.googlegroups.com:

> Thanks Sinan.


You are most welcome.

> I am not very familiar with Perl. I do not use it too often and when
> I come back to it after some time I invariably forget a lot of stuff
> that I had known before.


The ActiveState distribution does contain a fairly effective and very
pretty HTML version of the standard Perl documentation.

It is a good idea to take a look at the table of contents and the FAQ
every time you need to refresh your Perl information.

I usually find the command line easier:

perldoc perldoc
perldoc perltoc
perldoc perlfaq

perldoc -f function_name

perldoc -q faq_keyword

For example:

C:\> perldoc -q object

Found in C:\opt\Perl\lib\pod\perlfaq3.pod

Where can I learn about object-oriented Perl programming?

A good place to start is perltoot, and you can use perlobj, perlboot,
perltoot, perltooc, and perlbot for reference.

A good book on OO on Perl is the "Object-Oriented Perl" by Damian Conway
from Manning Publications, or "Learning Perl References, Objects, &
Modules" by Randal Schwartz and Tom Phoenix from O'Reilly Media.

Sinan

--
A. Sinan Unur <>
(remove .invalid and reverse each component for email address)
clpmisc guidelines: <URL:http://www.augustmail.com/~tadmc/clpmisc.shtml>

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ 2.17 What is perl.com? Perl Mongers? pm.org? perl.org? cpan.org? PerlFAQ Server Perl Misc 0 04-04-2011 10:00 PM
FAQ 1.4 What are Perl 4, Perl 5, or Perl 6? PerlFAQ Server Perl Misc 0 02-27-2011 11:00 PM
FAQ 2.17 What is perl.com? Perl Mongers? pm.org? perl.org? cpan.org? PerlFAQ Server Perl Misc 0 02-03-2011 11:00 AM
FAQ 1.4 What are Perl 4, Perl 5, or Perl 6? PerlFAQ Server Perl Misc 0 01-23-2011 05:00 AM
Perl Help - Windows Perl script accessing a Unix perl Script dpackwood Perl 3 09-30-2003 02:56 AM



Advertisments