I am new to Perl and am curious whether #{$list_ref} and #$list_ref are perfectly equivalent.
They seem to be interchangeable, but I am nervous that there is something subtle going on that I may be missing.
Yes, they're equivalent. You need braces when the expression is more than a simple scalar variable, e.g.,
push #{ $foo{$bar} } => "baz";
For more detail, see the Using References section of the documentation on references. The standard Perl documentation also includes several tutorials on using references:
Understand References Today (mentioned by hobbs in the question's comments)
Manipulating Arrays of Arrays in Perl
Perl Data Structures Cookbook
I've always found it helpful to remember that the outer braces are not syntactical magic, they're just a block that returns a reference. The expression inside the block can be anything that returns a reference:
$ perl -le 'sub foo {[qw/ apple orange banana /]} print ${print "Do something here."; foo()} [1]'
Do something here.
orange
Related
The question Is space supposed to be ignored between a sigil and its variable name? was answered positively.
What is the reason Perl interprets $ foo as $foo?
perl -w -E 'my $ foo = $$; say "Perl $]\n\$ foo = ", $foo'
Perl 5.028001
$ foo = 3492
Isn't it against The Syntax of Variable Names documentation?
That documentation only discusses the name, not the sigil. The sigil can always be separated from the name by space characters. It is definitely underdocumented and I would not suggest ever making use of it, but it is used.
Perl does not have sigils, it has "dereference" operators:
$test[1] means 'give me the scalar at the index 1 of the array called "test" from this scope'. That is why you can put spaces after the "sigil".
I don't understand why everybody keeps calling them sigils, it makes things very confusing. BASIC had sigils, PHP has sigils, but Perl 5 does not even if it looks like it has. I wish I had realized the "sigils" are in fact operators when I was learning Perl, understanding and parsing references and derefferencing would have been a lot easier, not to mention grokking symbol tree manipulation.
The "sigils" are not documented as "operators" in perldoc, but it is much easier to parse Perl code if you think of them as being operators.
Later, after discussion in the comments: here is how Perl 5 uses "sigils": https://www.oreilly.com/library/view/advanced-perl-programming/0596004567/ch01.html
Sorry for may be not clear question, but I'm asking it, because I don't like to read something without understanding what I'm reading about.
Here is the snippet from the "Programming Perl":
Since the way in which you dereference something always indicates what sort of
referent you’re looking for, a typeglob can be used the same way a reference can,
despite the fact that a typeglob contains multiple referents of various types. So
${*main::foo} and ${\$main::foo} both access the same scalar variable, although
the latter is more efficient.
For me this seems wrong, and that it would be right if it were this way:
you can use a typeglob instead of the scalar variable because reference is always a scalar and compiler knows what you need.
From the book's text, the reader can assume that a reference can be something other than a scalar variable (i.e. a scalar entry in the symbol table).
Once I saw a warning: use of array as a reference is deprecated, so it appears to me that long ago this paragraph in the "Programming Perl" was meaningful, because references could be not just scalars, but in the new 4th edition it simply was not changed to comply with modern Perl.
I checked the errata page for this book but found nothing.
Is my assumption correct? If not, would be somebody so pleasant to explain, where I'm wrong.
Thank you in advance.
No. What it's saying is that unlike a normal reference, a typeglob contains multiple types of things at the same time. But the way in which you dereference it indicates which type of thing you want:
use strict;
use warnings;
use 5.010;
our $foo = 'scalar';
our #foo = qw(array of strings);
our %foo = (key => 'value');
say ${ *foo }; # prints "scalar"
say ${ *foo }[0]; # prints "array"
say ${ *foo }{key}; # prints "value"
You don't need a special "typeglob dereferencing syntax" because the normal
dereferencing syntax already indicates which slot of the typeglob you want to dereference.
Note that this doesn't work with my variables, because lexical variables aren't associated with typeglobs.
Sidenote: The "array as a reference" warning is not related to this. It refers to this syntax: #array->[0] (meaning the same as $array[0]). That was never intended to be valid syntax; it slipped into the Perl 5 parser by accident and was deprecated once Larry noticed.
although this doesn't exactly answer your question, I can try to tell you what I experience with typeglobs
they are more dynamic than scalars and references, because using a typeglob is sort of a way telling the compiler "here is a hint, guess yourself what you have to do with it"
a reference always has a strict type and target. a typeglob may just contain a string, indicating that it's supposed to point to some variable(name) or filehandle (like STDOUT) or some other value, that's accessible through this string
there are perlish hacks to accomplish some strange things, that are only possible with typeglobs, so I think even in mordern perl they are important
PerlGuts illustrated is an accessible way to learn about Perl internals.
http://www.cpan.org/authors/id/GAAS/illguts-0.09.pdf
The answers given so far are illustrative of what's going on, but learning how perl stores variables will let you see the answer is actually very simple and analogies are actually less clear than the implementation.
PS: You are commendable in wanting to understand - it will stand you in good stead for the future :)
The code below is from an old Perl script.
print "%{#{$noss}[$i]}->{$sector} \n\n";
How should I rewrite the code above so that Perl does not complain that "using a hash as a reference is deprecated"? I have tried all sorts of way but I still couldn't quite get the hang of what the Perl compiler want me to do.
print "%{#{$noss}[$i]}->{$sector} \n\n";
should be nothing more than
print "$noss->[$i]{$sector} \n\n";
or even
print "$$noss[$i]{$sector} \n\n";
without all that rigamarole.
Guessing that $noss is a reference to an array of hash references, you can build a correct expression by following the simple rule of replacing
what would normally be an array or hash name (not including the $/#/%) with an expression giving a reference in curly braces.
So your array element, normally $foo[$i], becomes ${$noss}[$i]. That expression is itself a hashref, so to get an element from that hash, instead of $foo{$sector}, you use ${ ${$noss}[$i] }{$sector}.
This can also appear in various other forms, such as $noss->[$i]{$sector}; see http://perlmonks.org?node=References+quick+reference for simple to understand rules.
I agree with ysth and tchrist, and want to reiterate that $noss->[$i]{$sector} really is the best option for you. This syntax is more readable since it shows clearly that $noss is a reference and that you are taking the $ith element of it and further the $sector key from that element.
In terms of teaching to fish rather than giving out fish: you should read perldoc perlreftut and specifically the "use rules". Understanding these two "use rules" along with the extra "arrow rule" (yep only 3 rules) will give you a much better grasp on how to get going with references.
In the linked SO answer, Eric illustrates a way to call a subroutine, which accepts arrays by reference as arguments, and use the prototypes to allow the caller code to pass the array names without using reference operator \#; the way built-ins like push #array, $value do.
# Original code:
sub Hello { my ($x_ref, $y_ref) = #_; ...}
Hello(\#x, \#y);
# Same thing using array ref prototype:
sub Hello (\#\#$) {...}
Hello(#x, #y);
My question is, is this considered to be a Best Practice? And what are the guidelines on the pattern's use?
It seems like this pattern should either be used ONLY for built-ins, or for 100% of subroutines that accept array arguments in all of your code.
Otherwise code maintenance and use of your subs becomes fragile since the developer never knows whether a particular sub, when called, should be forced to reference an array or not.
An additional point of fragility is that you become confused between doing such calls and legitimately using two arrays combined into one using a comma operator.
On the positive side, using the pattern prevents the "forgot to reference the array" bugs, and makes the code calling the subroutines somewhat more readable.
P.S. I don't have Conway's book handy and don't recall if he ever discussed the topic, to pre-empt RTFB responses.
Only use prototypes when you're trying to extend Perl's syntax: e.g. if you're building Moose, or something like the examples in Dominus' Higher Order Perl. If you're doing that, you know enough to disregard PBP (and to annotate your code to shut Perl::Critic up). If you're doing anything else, don't use them.
Let's ask Perl::Critic:
echo "use strict; sub Hello (\#\#$) {...}" | perlcritic
Subroutine prototypes used at line 1, column 1. See page 194 of PBP. (Severity: 5)
Yeah, that would be a no.
I tend to think that anything that makes a subroutine act differently than any other subroutine isn't the best thing. There might be instances where it's a good idea, but in general it's more special cases, documentation, and other things to remember. The more your code acts like most other Perl code, the easier you make things for your users.
Notice that this isn't the main complaint that Perl Best Practices has with prototypes, which is an ugly kludge in Perl.
A recent question used a sigil invariant syntax %hash->{key} = 1; for hash access, which seems to work fine, but I would have thought it would be a syntax error.
It seems to work for arrays as well:
my #array;
#array->[3] = 6;
Is this behavior documented somewhere? I don't remember reading it, but may have overlooked it.
It seems to behave exactly like:
(\%hash)->{key}
rather than what I would have assumed:
(scalar %hash)->{key} # runtime error
Seems this was covered over at perlmonks: http://www.perlmonks.org/?node_id=171177
My reading of perlop has me convinced that this is an unintended
syntactic feature.
And that's exactly what it is. When using the arrow, Perl will see
whatever is left of it as a reference. Including if you have something
like #l or %h.
Note that you will get the warning
Using an array as a reference is deprecated in Perl 5.8.0.
Abigail