line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
### ### |
3
|
|
|
|
|
|
|
# Class::ArrayObjects - Utility class for array based objects # |
4
|
|
|
|
|
|
|
# Robin Berjon # |
5
|
|
|
|
|
|
|
# ------------------------------------------------------------------- # |
6
|
|
|
|
|
|
|
# 01/12/2003 - v1.02 support non-existing "with" # |
7
|
|
|
|
|
|
|
# 07/07/2003 - v1.01 patch by Slaven Rezic so that "extend" will look # |
8
|
|
|
|
|
|
|
# into @ISA in case the class isn't specified. # |
9
|
|
|
|
|
|
|
# 06/07/2002 - v1.00 clean up # |
10
|
|
|
|
|
|
|
# 21/04/2001 - v0.04 many many documentation updates + release # |
11
|
|
|
|
|
|
|
# 02/04/2001 - v0.03 feature upgrade in view of release # |
12
|
|
|
|
|
|
|
# 28/01/2001 - v0.02 a few enhancements and uses # |
13
|
|
|
|
|
|
|
# 12/12/2000 - v0.01 initial hack # |
14
|
|
|
|
|
|
|
### ### |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
package Class::ArrayObjects; |
18
|
|
|
|
|
|
|
|
19
|
1
|
|
|
1
|
|
8249
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
36
|
|
20
|
1
|
|
|
1
|
|
4
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
21
|
1
|
|
|
1
|
|
4
|
use vars qw($VERSION %packages); |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
280
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
$VERSION = '1.03'; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
#---------------------------------------------------------------------# |
27
|
|
|
|
|
|
|
# import() |
28
|
|
|
|
|
|
|
# this is where all the work gets done, at load |
29
|
|
|
|
|
|
|
#---------------------------------------------------------------------# |
30
|
|
|
|
|
|
|
sub import { |
31
|
4
|
|
|
4
|
|
151
|
my $class = shift; |
32
|
4
|
50
|
|
|
|
12
|
@_ or return; |
33
|
|
|
|
|
|
|
|
34
|
4
|
|
|
|
|
11
|
my $pkg = caller; |
35
|
4
|
|
|
|
|
6
|
my $method = shift; |
36
|
4
|
|
|
|
|
3
|
my $options = shift; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
### grab the start index and the fields |
39
|
4
|
|
|
|
|
6
|
my ($idx, @fld, @real_fld); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# for basic definition |
42
|
4
|
100
|
|
|
|
15
|
if ($method eq 'define') { |
|
|
50
|
|
|
|
|
|
43
|
1
|
|
50
|
|
|
5
|
$options->{fields} ||= []; |
44
|
1
|
|
|
|
|
3
|
$idx = 0; |
45
|
1
|
|
|
|
|
1
|
@fld = @{$options->{fields}}; |
|
1
|
|
|
|
|
7
|
|
46
|
1
|
|
|
|
|
3
|
@real_fld = @fld; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# for extension |
50
|
|
|
|
|
|
|
elsif ($method eq 'extend') { |
51
|
3
|
|
50
|
|
|
9
|
$options->{with} ||= []; |
52
|
|
|
|
|
|
|
{ |
53
|
1
|
|
|
1
|
|
5
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
536
|
|
|
3
|
|
|
|
|
4
|
|
54
|
3
|
100
|
66
|
|
|
13
|
if (not defined $options->{class} and @{ $pkg . '::ISA' } == 1) { |
|
1
|
|
|
|
|
7
|
|
55
|
1
|
|
|
|
|
7
|
$options->{class} = ${ $pkg . '::ISA' }[0]; |
|
1
|
|
|
|
|
5
|
|
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
} |
58
|
3
|
50
|
|
|
|
11
|
die "[$pkg]: can't extend undefined class $options->{class} with package $pkg" |
59
|
|
|
|
|
|
|
unless defined $packages{$options->{class}}; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# get what is needed to store the real idx |
62
|
3
|
|
|
|
|
4
|
@real_fld = (@{$packages{$options->{class}}}, @{$options->{with}}); |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
27
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# support import of parent fields |
65
|
3
|
100
|
|
|
|
8
|
if ($options->{import}) { |
66
|
1
|
|
|
|
|
2
|
$idx = 0; |
67
|
1
|
|
|
|
|
4
|
@fld = @real_fld; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
else { |
70
|
2
|
|
|
|
|
3
|
$idx = $#{$packages{$options->{class}}} + 1; |
|
2
|
|
|
|
|
6
|
|
71
|
2
|
|
|
|
|
4
|
@fld = @{$options->{with}}; |
|
2
|
|
|
|
|
13
|
|
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# there was an error |
76
|
|
|
|
|
|
|
else { |
77
|
0
|
|
|
|
|
0
|
die "[$pkg]: first arg must be 'define' or 'extend'"; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# now lets create the subs |
81
|
4
|
|
|
|
|
8
|
for my $enum (@fld) { |
82
|
11
|
|
|
|
|
21
|
my $qname = "${pkg}::$enum"; |
83
|
11
|
|
|
|
|
14
|
my $value = $idx; |
84
|
11
|
|
|
0
|
|
116
|
*$qname = sub () { $value }; |
|
0
|
|
|
|
|
0
|
|
85
|
11
|
|
|
|
|
28
|
$idx++; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# another way of doing it: |
88
|
|
|
|
|
|
|
# eval "sub ${pkg}::$enum () { $idx }"; |
89
|
|
|
|
|
|
|
# die "[$pkg]: $@" if $@; |
90
|
|
|
|
|
|
|
# $idx++ |
91
|
|
|
|
|
|
|
} |
92
|
4
|
|
|
|
|
10
|
$packages{$pkg} = \@real_fld; # store the fields for extension |
93
|
4
|
|
|
|
|
2422
|
return 1; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
#---------------------------------------------------------------------# |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
1; |
100
|
|
|
|
|
|
|
=pod |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head1 NAME |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Class::ArrayObjects - utility class for array based objects |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=head1 SYNOPSIS |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
package Some::Class; |
109
|
|
|
|
|
|
|
use Class::ArrayObjects define => { |
110
|
|
|
|
|
|
|
fields => [qw(_foo_ _bar_ BAZ)], |
111
|
|
|
|
|
|
|
}; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
or |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
package Other::Class; |
116
|
|
|
|
|
|
|
use base 'Some::Class'; |
117
|
|
|
|
|
|
|
use Class::ArrayObjects extend => { |
118
|
|
|
|
|
|
|
class => 'Some::Class', |
119
|
|
|
|
|
|
|
with => [qw(_zorg_ _fnord_ BEZ)], |
120
|
|
|
|
|
|
|
import => 1, |
121
|
|
|
|
|
|
|
}; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 DESCRIPTION |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
This module is little more than a cute way of defining constant subs |
126
|
|
|
|
|
|
|
in your own package. Constant subs are very useful when dealing with |
127
|
|
|
|
|
|
|
array based objects because they allow one to access array slots by |
128
|
|
|
|
|
|
|
name instead of by index. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head2 Why use arrays for objects instead of hashes ? |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
There are two apparently compelling reasons to use arrays for objects |
133
|
|
|
|
|
|
|
instead of hashes. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
First: speed. In my benchmarks on a few boxes around here I've seen |
136
|
|
|
|
|
|
|
arrays be faster by 30%. I must admit that my benchmarks weren't |
137
|
|
|
|
|
|
|
perfect as I wasn't all that interested in speed per se, only in |
138
|
|
|
|
|
|
|
knowing whether I was to take a serious performance hit or not (I was |
139
|
|
|
|
|
|
|
nevertheless pleasantly surprised to note the opposite, it can't |
140
|
|
|
|
|
|
|
hurt). |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Second: memory. Memory was much more important to me as I was |
143
|
|
|
|
|
|
|
targeting a mod_perl environment where every bit of memory tends to |
144
|
|
|
|
|
|
|
count. Depending on how they are used, arrays use from 30% up to 65% |
145
|
|
|
|
|
|
|
less space than hashes. As a rule of thumb the more keys you have, the |
146
|
|
|
|
|
|
|
more you may save. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
It must be said though that despite the fact that I happened to be |
149
|
|
|
|
|
|
|
looking for ways to save space, it's not a reason to jump into array |
150
|
|
|
|
|
|
|
based objects and start converting every single hash you have to an |
151
|
|
|
|
|
|
|
array. Yes, I did see some of my processes lose I<~3Mo> of unshared |
152
|
|
|
|
|
|
|
memory so there are definitely cases when it's useful. Such cases are |
153
|
|
|
|
|
|
|
usually when you have lots of objects and/or structures that are |
154
|
|
|
|
|
|
|
fairly similar in nature (ie have the same keys) but contain different |
155
|
|
|
|
|
|
|
values. I don't know how Perl works internally but it would seem only |
156
|
|
|
|
|
|
|
logical that it has to store the keys with every hash, whereas using |
157
|
|
|
|
|
|
|
arrays there are no keys (which is why this package exists: to provide |
158
|
|
|
|
|
|
|
you with something that looks like keys into arrays). |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
In addition to that, this package can be seen as twisting slightly the |
161
|
|
|
|
|
|
|
view on how to do OO in Perl, encouraging some limited encapsulation |
162
|
|
|
|
|
|
|
of fields and extension subclassing rather than override subclassing |
163
|
|
|
|
|
|
|
(the latter really being a matter of taste). |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 Why not pseudo-hashes ? |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Pseudo-hashes never appealed to me, they always seemed to have been |
168
|
|
|
|
|
|
|
hacked on top of Perl. They never left experimental status, which |
169
|
|
|
|
|
|
|
probably says a lot already. A number of things that work with hashes |
170
|
|
|
|
|
|
|
and arrays don't work with them (and development seems to have |
171
|
|
|
|
|
|
|
stopped). And overall, they usually end up not saving you any space |
172
|
|
|
|
|
|
|
anyway. Pseudo-hashes must die. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=head2 Why Class::ArrayObjects ? |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
But why then use this class instead of the C or C |
177
|
|
|
|
|
|
|
modules ? Because it adds extra sugar (yum). |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Its main advantage over C (imho of course) is that you don't |
180
|
|
|
|
|
|
|
have to define the value of each field. Less typing, more readability. |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
C also provides that plus but it enforces naming rules in a |
183
|
|
|
|
|
|
|
way which I find limiting (it probably has very good reasons to do so, |
184
|
|
|
|
|
|
|
but I think that they don't apply in the context of array based |
185
|
|
|
|
|
|
|
objects). This module only complains if you try to use a field name |
186
|
|
|
|
|
|
|
that isn't a valid Perl sub name. (Note: right now it doesn't even |
187
|
|
|
|
|
|
|
complain because I was convinced when I wrote it that Perl would. But |
188
|
|
|
|
|
|
|
it turns out that you are perfectly allowed to define a sub with a |
189
|
|
|
|
|
|
|
forbidden name. Whether this is a bug or a feature, I don't know). |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
And last but not least, it defines a way to allow for inheritance |
192
|
|
|
|
|
|
|
while using array based objects. A major drawback of array based |
193
|
|
|
|
|
|
|
objects is that unlike with hashes, if your base class adds a field, |
194
|
|
|
|
|
|
|
you have to move all your fields' indices up by one. You shouldn't |
195
|
|
|
|
|
|
|
have to know such things, or even to care about it. |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Here, instead of using the C option (which creates fields in |
198
|
|
|
|
|
|
|
a class), simply use the C option. Tell it which class to |
199
|
|
|
|
|
|
|
extend (it needs to be already loaded, and must use |
200
|
|
|
|
|
|
|
Class::ArrayObjects to define its fields too) and which fields to add. |
201
|
|
|
|
|
|
|
Class::ArrayObjects takes care of counting from the right index in |
202
|
|
|
|
|
|
|
your subclass. It can't do multiple inheritance, and unless someone |
203
|
|
|
|
|
|
|
hacks it in somehow I doubt it ever will. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
You may use the C option to require that your parents' fields |
206
|
|
|
|
|
|
|
be defined in your own package too, so that you can access them. It is |
207
|
|
|
|
|
|
|
off by default so that you can use fields with the same names as those |
208
|
|
|
|
|
|
|
of your superclasse(s) (which is a plus over hash based objects) and |
209
|
|
|
|
|
|
|
also to avoid defining subs all over your package without you knowing |
210
|
|
|
|
|
|
|
about them. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
It may be worth noting that the added functionality doesn't get in the |
213
|
|
|
|
|
|
|
way, and using this to define constants is just as fast as using |
214
|
|
|
|
|
|
|
C or C. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head1 USING Class::ArrayObjects |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
There are two ways to use Class::ArrayObjects, either to simply define |
219
|
|
|
|
|
|
|
fields to use in your own objects, or to extend fields defined in a |
220
|
|
|
|
|
|
|
superclass of your. In a wild burst of creative naming I thus spawned |
221
|
|
|
|
|
|
|
into existence two options named respectively C and C. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
The way the two are used is the same: |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
use Class::ArrayObjects I => I |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 The define option |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
package Some::Class; |
230
|
|
|
|
|
|
|
use Class::ArrayObjects define => { |
231
|
|
|
|
|
|
|
fields => [qw(_foo_ _bar_ BAZ)], |
232
|
|
|
|
|
|
|
}; |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
C has only one option: C. It is an arrayref of strings |
235
|
|
|
|
|
|
|
which are the names of the fields you wish to use. They can be anything, |
236
|
|
|
|
|
|
|
so long as they are valid Perl sub names. |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=head2 The extend option |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
package Other::Class; |
241
|
|
|
|
|
|
|
use base 'Some::Class'; |
242
|
|
|
|
|
|
|
use Class::ArrayObjects extend => { |
243
|
|
|
|
|
|
|
class => 'Some::Class', |
244
|
|
|
|
|
|
|
with => [qw(_zorg_ _fnord_ BEZ)], |
245
|
|
|
|
|
|
|
import => 1, |
246
|
|
|
|
|
|
|
}; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
C has three options: |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=over 4 |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=item * class |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
This defines the class to extend (it must also use Class::ArrayObjects |
255
|
|
|
|
|
|
|
and have been loaded previously). If that class is not specified, it will |
256
|
|
|
|
|
|
|
look at @ISA. If @ISA contains only one item it will use that one. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=item * with |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
This is exactly equivalent to C except that it reads better to |
261
|
|
|
|
|
|
|
have extend class Foo with x,y,z. |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=item * import |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
Defaulting to false, setting it to any true value will make your |
266
|
|
|
|
|
|
|
superclasses' fields also defined in your package. This can be needed |
267
|
|
|
|
|
|
|
at times, though I wouldn't encourage its use. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=back |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=head2 After that ? |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
After you've defined fields, all you have to do is use them as indices |
274
|
|
|
|
|
|
|
to your arrays. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
package Some::Class; |
277
|
|
|
|
|
|
|
use Class::ArrayObjects define => { |
278
|
|
|
|
|
|
|
fields => [qw(_foo_ _bar_ BAZ)], |
279
|
|
|
|
|
|
|
}; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
my @arry = qw(zorg stuff blurp); |
282
|
|
|
|
|
|
|
print $arry[_bar_]; # stuff |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
Any operation you can do on arrays with numeric indices works exactly |
285
|
|
|
|
|
|
|
the same way. The only difference is that you are using names, which |
286
|
|
|
|
|
|
|
are much easier to remember. There is no performance penalty for this, |
287
|
|
|
|
|
|
|
Perl is smart enough to inline the return values of constant subs so |
288
|
|
|
|
|
|
|
that when in the above example you say _bar_ it really sees 1. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=head2 A note to mod_perl users |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
The contexts in which I use this module are mostly mod_perl related. |
293
|
|
|
|
|
|
|
In fact, one of the reasons I created it was to allow for the space |
294
|
|
|
|
|
|
|
efficient representation of many objects. It may be further |
295
|
|
|
|
|
|
|
optimizable, but so far it has already seemed to work well. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
You can preload this module without defining any fields as follows: |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
use Class::ArrayObjects qw(); |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
In that case, C will not be called and nothing will happen |
302
|
|
|
|
|
|
|
other then the preloading of the code. As a precaution, even if it |
303
|
|
|
|
|
|
|
were called it would return immediately. |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
I do recommend that you preload all modules that are based on |
306
|
|
|
|
|
|
|
Class::ArrayObjects so that the data it stores internally about which |
307
|
|
|
|
|
|
|
fields belong to which classes (in order to allow for extension) |
308
|
|
|
|
|
|
|
remains shared by all the processes. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head1 BUGS AND CAVEATS |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
I don't know of any outstanding bugs presently but it is not |
313
|
|
|
|
|
|
|
impossible that some may have filtered out. I have been using this |
314
|
|
|
|
|
|
|
module in production for some time now, and it appears to be behaving |
315
|
|
|
|
|
|
|
with stability. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Of course, you mustn't define a field in your package with the same |
318
|
|
|
|
|
|
|
name as another sub. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
As a rule of thumb, I find that this kind of class works better for |
321
|
|
|
|
|
|
|
extension subclasses than for override subclasses, but YMMV. |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head1 TODO |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
- add an interface to allow people to mess with the internals on |
326
|
|
|
|
|
|
|
demand |
327
|
|
|
|
|
|
|
- add serialisation helpers to allow one to persist an object based |
328
|
|
|
|
|
|
|
on Class::ArrayObjects and later retrieve it regardless of whether |
329
|
|
|
|
|
|
|
the order of the fields have changed or not. |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 ACKNOWLEDGMENTS |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Greg Bacon's for his article I
|
334
|
|
|
|
|
|
|
Arrays> which I read ages ago and inspired this module, one of the |
335
|
|
|
|
|
|
|
first I put on CPAN. |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
Slaven Rezic for the @ISA patch. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=head1 AUTHOR |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
Robin Berjon, robin@knowscape.com |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=head1 COPYRIGHT |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Copyright (c) 2000-2002 Robin Berjon. All rights reserved. This program is |
346
|
|
|
|
|
|
|
free software; you can redistribute it and/or modify it under the same terms |
347
|
|
|
|
|
|
|
as Perl itself. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head1 SEE ALSO |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
nothing that I can think of... |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=cut |
354
|
|
|
|
|
|
|
|