prefetcher
prefetcher

Reputation: 63

Perl operators that modify inputs in-place

I recently took a Perl test and one of the questions was to find all the Perl operations that can be used to modify their inputs in-place. The options were

I don't think any of these can modify the inputs in-place. Am I missing anything here or is the question wrong?

Upvotes: 1

Views: 349

Answers (2)

tobyink
tobyink

Reputation: 13664

Try this:

my @array = qw(1 2 3 4);
print "@array\n";

my @new_array = map ++$_, @array;

print "@new_array\n";
print "@array\n";  # oops, we modified this in-place

grep is similar. For sort, the $a and $b variables are aliases back to the original array, so can also be used to modify it. The result is somewhat unpredictable, depending on what sorting algorithm Perl is using (which has historically changed in different versions of Perl, though hasn't changed in a while).

my @arr = qw(1 2 3 4 5);
my @new = sort { ++$a } @arr;
print "@arr\n";

do and eval can take an arbitrary code block, so can obviously modify any non-readonly variable, though it's not clear whether that counts as modifying inputs in place. Slade's example using the stringy form of eval should certainly count though.

Upvotes: 1

Slade
Slade

Reputation: 1364

I'm assuming the question is testing to see if the student knows to properly use the return values of sort, map, and so on instead of using them in void context and expecting side effects. It's totally possible to modify the parameters given, though.

map and grep alias $_ to each element, so modifying $_ will change the values of the variables in the list passed to it (assuming they're not constants or literals).

eval EXPR and do EXPR can do anything, more or less, so there's nothing stopping you from doing something like:

my $code = q($code = 'modified');
eval $code;
say $code;

The arguments to do BLOCK and eval BLOCK are always a literal block of code, which aren't valid lvalues in any way I know of.

sort has a special optimization when called like @array = sort { $a <=> $b } @array;. If you look at the opcodes generated by this with B::Concise, you'll see something like:

9  <@> sort lK/INPLACE,NUM

But for a question about the language semantics, an implementation detail is irrelevant.

Upvotes: 1

Related Questions