You already think about it. If you use an array for your list instead of a hash, you do not need to worry about the head and the latter. The head of the array is $array[0] , and the last element is $array[-1] . Simple and convenient.
Here's a quick definition of a standard class for defining a list. I just defined a constructor (new routine) and one method (list).
package Local::List; sub new { my $class = shift; my $self = {}; bless $self, $class; $self->list([]); } sub list { my $self = shift; my $list_ref = shift; if (ref $list_ref ne "ARRAY) { return; } if (defined $list_ref) { $self->{LIST} = $list_ref; } if wantarray { return $self->{LIST}; } }
First: use the same standard names that everyone else uses. Use new for constructor. When I try to look at the documentation on how to use your class, I can find the word new and find out how I create the class object. Also use the variable names $class and $self . This is what everyone else is doing, so it’s easy to understand what is happening.
Note that in my new routine, the first element passed is the name of the class, and the first element passed to my other routines is a reference to my class object (i.e. $self ). This is probably the most difficult to understand classes.
Pay attention to new , I immediately create my $self and bless it. That way, I can call my other routines (my methods) to do the tuning for me. Thus, my constructor does not know how my class is structured. This has many advantages:
- When (not if) I change my class, I do not need to change the constructor.
- My constructor is always synchronized with all my methods.
- I do not need to know how a class object is structured when I start defining a class. I can start writing my class without worrying about all these dirty details about how it will work.
Note that the list routine (or method) can either set the list or return a list. This is much simpler if you use the same routine to set or get a value. Also, in method routines, use null return when the method function returns an error. Otherwise, always return something. This makes it easy to check if the method worked or not.
Take a look at some of the other methods that you probably want. Let all four standard list functions:
Here is an example:
sub push { my $self = shift; my $member = shift; if (not defined $member) { return; } my $list_ref = $self->list; my $return = push @{ $list_ref }, $member; $self->list($list_ref); return $return; }
Wow, that’s easy. Note that pop doesn't know what my class looks like. He used the list method to get a link to a list. He then used the built-in push method to insert the item into the list. I store this return value, and this is what I will return. I'm not even sure what push returns. All I know is that push returns something if it succeeds. (Yes, I know that it returns the number of elements in the list).
The other three functions are more or less the same. Here are a few more:
- current
- splicing
- Following
- previous
- head
- the last
All you have to do for the current is to keep the current value. Use the same function to set and get the value. Note that my list method or my push method or my new constructor knows or cares about how you store it. Do not use our next and previous methods. All they need to do is increase or decrease the value of current and save it using the routine of the current method:
sub next { my $self = shift my @list = $self->list;
And now, based on your question: getting the last and main values of the list. Here is the last
sub last { my $self = shift; my $list_ref = $self->list; return ${ $list_ref }[-1]; }
And a quick copy and paste will give me a head:
sub head { my $self = shift; my $list_ref = $self->list; return ${ $list_ref }[0]; }
What is it! Everything that bothered you was in vain.
Sorry for the long post. I just wanted to emphasize that object-oriented programming in Perl is not so difficult if you follow a few simple guidelines.
(Simple? How about use Moose; No, I just said!) .; -)