Learning Perl Objects, References amp;amp; Modules [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Learning Perl Objects, References amp;amp; Modules [Electronic resources] - نسخه متنی

Randal L. Schwartz

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید














4.5 Creating an Anonymous Array Directly


In the
get_provisions_list routine earlier, you created a
half dozen array names that were used only so that you could take a
reference to them immediately afterward. When the subroutine exited,
the array names all went away, but the references remained.

While creating temporarily named arrays would work in the simplest
cases, creating such names becomes more complicated as the data
structures become more detailed. You'd have to keep
thinking of names of arrays just so you can forget them shortly
thereafter.

You can reduce the namespace
clutter by narrowing down the scope of the various array names.
Rather than letting them be declared within the scope of the
subroutine, you can create a temporary block:

my @skipper_with_name;
{
my @skipper = qw(blue_shirt hat jacket preserver sunscreen);
@skipper_with_name = ("The Skipper", \@skipper);
}

At this point, the second element of
@skipper_with_name is a reference to the array
formerly known as @skipper. However, the name is
no longer relevant.

This is a lot of typing to simply say
"the second element should be a reference to an
array containing these elements." You can create
such a value directly using the anonymous array
constructor, which is Yet Another Use for square brackets:

my $ref_to_skipper_provisions =
[ qw(blue_shirt hat jacket preserver sunscreen) ];

The square brackets take the value within (evaluated in a list
context); establish a new, anonymous array initialized to those
values; and (here's the important part) return a
reference to that array. It's as if you said:

my $ref_to_skipper_provisions;
{
my @temporary_name =
( qw(blue_shirt hat jacket preserver sunscreen) );
$ref_to_skipper_provisions = \@temporary_name;
}

Here you
don't need to come up with a temporary name, and you
don't need the extra noise of the temporary block.
The result of a square-bracketed anonymous array constructor is an
array reference, which fits wherever a scalar variable fits.

Now you can use it to construct the larger list:

my $ref_to_skipper_provisions =
[ qw(blue_shirt hat jacket preserver sunscreen) ];
my @skipper_with_name = ("The Skipper", $ref_to_skipper_provisions);

Of course, you didn't actually need that scalar
temporary, either. You can put a scalar reference to an array as part
of a larger list:

my @skipper_with_name = (
"The Skipper",
[ qw(blue_shirt hat jacket preserver sunscreen) ]
);

Now let's walk through this. You've
declared @skipper_with_name, the first element of
which is the Skipper's name string, and the second
element is an array reference, obtained by placing the five
provisions into an array and taking a reference to it. So
@skipper_with_name is only two elements long, just
as before.

Don't confuse the
square brackets with the parentheses here. They each have their
distinct purpose. If you replace the square brackets with
parentheses, you end up with a six-element list. If you replace the
outer parentheses (on the first and last lines) with square brackets,
you construct an anonymous array that's two elements
long and then take the reference to that array as the only element of
the ultimate @skipper_with_name array.[2]

[2] In classrooms, we've seen that too much
indirection (or not enough indirection) tends to contribute to the
most common mistakes made when working with references.


So, in summary, the syntax:

my $fruits;
{
my @secret_variable = ('pineapple', 'papaya', 'mango');
$fruits = \@secret_variable;
}

can be simply replaced with:

my $fruits = ['pineapple', 'papaya', 'mango'];

Does this work for more complicated
structures? Yes! Any time you need an element of a list to be a
reference to an array, you can create that reference with an
anonymous array constructor. In fact, you can also nest them in your
provisions list:

sub get_provisions_list {
return (
["The Skipper",
[qw(blue_shirt hat jacket preserver sunscreen)]
],
["The Professor",
[qw(sunscreen water_bottle slide_rule batteries radio)]
],
["Gilligan",
[qw(red_shirt hat lucky_socks water_bottle)]
],
);
}
my @all_with_names = get_provisions_list( );

Walking through this from the outside in, you have a return value of
three elements. Each element is an array reference, pointing to an
anonymous two-element array. The first element of each array is a
name string, while the second element is a reference to an anonymous
array of varying lengths naming the provisionsall without
having to come up with temporary names for any of the intermediate
layers.

To the caller of this subroutine, the return value is identical to
the previous version. However, from a maintenance point of view, the
reduced clutter of not having all the intermediate names saves screen
and brain space.

You can show a reference to an empty anonymous hash using an empty
anonymous array constructor. For example, if you add one
"Mrs. Howell" to that fictional
travel list, as someone who has packed rather light,
you'd simply insert:

["Mrs. Howell",
[ ]
],

This is a single element of the larger list. This item is a reference
to an array with two elements, the first of which is the name string,
and the second of which is itself a reference to an empty anonymous
array. The array is empty because Mrs. Howell hasn't
packed anything for this trip.



/ 199