What are the differences between #variable and $variable in Perl?
I have read code with the symbol $ and the symbol # before a variable name.
For example:
$info = "Caine:Michael:Actor:14, Leafy Drive";
#personal = split(/:/, $info);
What are the difference between a variable containing $ as opposed to #?
It isn't really about the variable, but more about the context how the variable is used. If you put a $ in front of the variable name, then it is used in scalar context, if you have a # that means you use the variable in list context.
my #arr; defines variable arr as array
when you want to access one individual element (that is a scalar context), you have to use $arr[0]
You can find more about Perl contexts here: http://www.perlmonks.org/?node_id=738558
All your knowledge about Perl will be crashed with mountains, when you don't feel context of this language.
As many people, you use in your speech single value (scalars) and many things in a set.
So, the difference between all of them:
i have a cat. $myCatName = 'Snowball';
it jump on bed where sit #allFriends = qw(Fred John David);
And you can count them $count = #allFriends;
but can't count them at all cause list of names not countable: $nameNotCount = (Fred John David);
So, after all:
print $myCatName = 'Snowball'; # scalar
print #allFriends = qw(Fred John David); # array! (countable)
print $count = #allFriends; # count of elements (cause array)
print $nameNotCount = qw(Fred John David); # last element of list (uncountable)
So, list is not the same, as an array.
Interesting feature is slices where your mind will play a trick with you:
this code is a magic:
my #allFriends = qw(Fred John David);
$anotherFriendComeToParty =qq(Chris);
$allFriends[#allFriends] = $anotherFriendComeToParty; # normal, add to the end of my friends
say #allFriends;
#allFriends[#allFriends] = $anotherFriendComeToParty; # WHAT?! WAIT?! WHAT HAPPEN?
say #allFriends;
so, after all things:
Perl have an interesting feature about context. your $ and # are sigils, that help Perl know, what you want, not what you really mean.
$ like s, so scalar
# like a, so array
Variables that start $ are scalars, a single value.
$name = "david";
Variables that start # are arrays:
#names = ("dracula", "frankenstein", "dave");
If you refer to a single value from the array, you use the $
print "$names[1]"; // will print frankenstein
From perldoc perlfaq7
What are all these $#%&* punctuation signs, and how do I know when to use them?
They are type specifiers, as detailed in
perldata:
$ for scalar values (number, string or reference)
# for arrays
% for hashes (associative arrays)
& for subroutines (aka functions, procedures, methods)
* for all types of that symbol name. In version 4 you used them like
pointers, but in modern perls you can just use references.
$ is for scalar variables(in your case a string variable.)
# is for arrays.
split function will split the variable passed to it acoording to the delimiter mentioned(:) and put the strings in the array.
Variable name starts with $ symbol called scalar variable.
Variable name starts with # symbol called array.
$var -> can hold single value.
#var -> can hold bunch of values ie., it contains list of scalar values.
Related
I want to split a scalar by whitespaces and save the result in an ArrayReference.
use strict;
use warnings;
use Data::Dumper;
my $name = 'hans georg mustermann';
my $array = split ' ', $name;
print Dumper($array); #$VAR1 = 3;
So it seems $array is now a scalar with the size resulted by the split operation.
When i change the code to my $array = [split ' ', $name]; the variable $array is now a ArrayReference and contains all 3 strings.
I just don't understand this behavior. Would be really great if someone could explain it to me or post a good documentation about these things, as i don't know how to search for this topic.
Thank you in advance
What you see here is called "context". The documentation about this is rather scattered. You also want to take a look at this tutorial about "scalar vs list context" https://perlmaven.com/scalar-and-list-context-in-perl
If you assign the result of split (or any subroutine calls) to an array, it's list context:
my #arr = split ' ', $name;
#=> #arr = ('hans', 'georg', 'mustermann');
What your example code shows is assigning them to a scalar -- and therefore it's under "scalar context".
Since, naturally, multiple things cannot fit into one position, some sort of summarization needs to be done. In the case of split function, perl5 has defined that the number of elements in the result of split shall be the best.
Check the documentation of the split function: https://perldoc.pl/functions/split -- which actually defines the behaviour under scalar context as well as list context.
Also take a glance at the documentation of all builtin functions at https://perldoc.pl/functions -- you'll find the behaviour definition under "list context" and "scalar context" for most of them -- although many of them are not returning "the size of lists" but rather something else.
That's called context.
The partial expression split ' ', $name evaluates to a list. The partial expression $array = LIST coerces the list to a scalar value, namely counting the number of elements in the list. That's the default behaviour of lists in scalar context.
You should write #array = LIST instead, using an array variable, not a scalar variable, in order to preserve the list values.
If you read the documentation for split(), you'll find the bit that explains what the function returns.
Splits the string EXPR into a list of strings and returns the list in list context, or the size of the list in scalar context.
You're calling the function in scalar context (because you're assigning the result of the call to a scalar variable) so you're getting the size of the list.
If you want to get the list, then you need to store it either in a list of variables:
my ($forename, $middlename, $surname) = split ' ', $name;
Or (more usually) in an array:
my #name_parts = split ' ', $name;
But actually, you say that you want an array reference. You can do that by calling split() inside an anonymous array constructor ([ ... ]) and assigning the result of that call to a scalar variable.
my $name_parts = [ split ' ', $name ];
I'm converting perl script to python.
I haven't used perl language before so many things in perl confused me.
For example, below, opt was declared as a scalar first but declared again as a hash. %opt = ();
Is it possible to declare a scalar and a hash with the same name in perl?
As I know, foreach $opt (#opts) means that scalar opt gets values of array opts one by one. opt is an array at this time???
In addition, what does $opt{$opt} mean?
opt outside $opt{$opt} is a hash and opt inside $opt{$opt} is a scalar?
I'm so confused, please help me ...
sub ParseOptions
{
local (#optval) = #_;
local ($opt, #opts, %valFollows, #newargs);
while (#optval) {
$opt = shift(#optval);
push(#opts,$opt);
$valFollows{$opt} = shift(#optval);
}
#optArgs = ();
%opt = ();
arg: while (defined($arg = shift(#ARGV))) {
foreach $opt (#opts) {
if ($arg eq $opt) {
push(#optArgs, $arg);
if ($valFollows{$opt}) {
if (#ARGV == 0) {
&Usage();
}
$opt{$opt} = shift(#ARGV);
push(#optArgs, $opt{$opt});
} else {
$opt{$opt} = 1;
}
next arg;
}
}
push(#newargs,$arg);
}
#ARGV = #newargs;
}
In Perl types SCALAR, ARRAY, and HASH are distinguished by the leading sigil in the variable name, $, #, and % respectively, but otherwise they may bear the same name. So $var and #var and %var are, other than belonging to the same *var typeglob, completely distinct variables.
A key for a hash must be a scalar, let's call it $key. A value in a hash must also be a scalar, and the one corresponding to $key in the hash %h is $h{$key}, the leading $ indicating that this is now a scalar. Much like an element of an array is a scalar, thus $ary[$index].
In foreach $var (#ary) the scalar $var does not really "get values" of array elements but rather aliases them. So if you change it in the loop you change the element of the array.
(Note, you have the array #opts, not #opt.)
A few comments on the code, in the light of common practices in modern Perl
One must always have use warnings; on top. The other one that is a must is use strict, as it enforces declaration of variables with my (or our), promoting all kinds of good behavior. This restricts the scope of lexical (my) variables to the nearest block enclosing the declaration
A declaration may be done inside loops as well, allowing while (my $var = EXPR) {} and foreach my $var (LIST) {}, and then $var is scoped to the loop's block (and is also usable in the rest of the condition)
The local is a different beast altogether, and in this code those should be my instead
Loop labels like arg: are commonly typed in block capitals
The & in front of a function name has rather particular meanings† and is rarely needed. It is almost certainly not needed in this code
Assignment of empty list like my #optArgs = () when the variable is declared (with my) is unneeded and has no effect (with a global #name it may be needed to clear it from higher scope)
In this code there is no need to introduce variables first since they are global and thus created the first time they are used, much like in Python – Unless they are used outside of this sub, in which case they may need to be cleared. That's the thing with globals, they radiate throughout all code
Except for the last two these are unrelated to your Python translation task, for this script.
† It suppresses prototypes; informs interpreter (at runtime) that it's a subroutine and not a "bareword", if it hasn't been already defined (can do that with () after the name); ensures that the user-defined sub is called, if there is a builtin of the same name; passes the caller's #_ (when without parens, &name); in goto &name and defined ...
See, for example, this post and this post
First, to make it clear, in perl, as in shell, you could surround variable names in curly brackets {} :
${bimbo} and $bimbo are the same scalar variable.
#bimbo is an array pointer ;
%bimbo is a hash pointer ;
$bimbo is a scalar (unique value).
To address an array or hash value, you will have to use the '$' :
$bimbo{'index'} is the 'index' value of hash %bimbo.
If $i contains an int, such as 1 for instance,
$bimbo[$i] is the second value of the array #bimbo.
So, as you can see, # or % ALWAYS refers to the whole array, as $bimbo{} or $bimbo[] refers to any value of the hash or array.
${bimbo[4]} refers to the 5th value of the array #bimbo ; %{bimbo{'index'}} refers to the 'index' value of array %bimbo.
Yes, all those structures could have the same name. This is one of the obvious syntax of perl.
And, euhm… always think in perl as a C++ edulcored syntax, it is simplified, but it is C.
I am currently learning about 'dereferencing' in Perl and need your help in understanding what the '\' means in the line below..
$ra = \$a;
As I have elsewhere previously written…
Unary \ creates a reference to whatever follows it. Used on a list, it creates a list of references.
Do not confuse this behavior with the behavior of backslash within a string, although both forms do convey the vaguely negational notion of protecting the next thing from interpretation. This resemblance is not entirely accidental.
You can create a reference to any named variable or subroutine with a backslash. You may also use it on an anonymous scalar value like 7 or "camel", although you won’t often need to. This operator works like the & (address-of) operator in C or C⁺⁺— at least at first glance.
Here are some examples:
$scalarref = \$foo;
$constref = \186_282.42;
$arrayref = \#ARGV;
$hashref = \%ENV;
$coderef = \&handler;
$globref = \*STDOUT;
The backslash operator can do more than produce a single reference. It will generate a whole list of references if applied to a list.
As mentioned earlier, the backslash operator is usually used on a single referent to generate a single reference, but it doesn’t have to be. When used on a list of referents, it produces a list of corresponding references. The second line of the following example does the same thing as the first line, since the backslash is automatically distributed throughout the whole list.
#reflist = (\$s, \#a, \%h, \&f); # List of four references
#reflist = \($s, #a %h, &f); # Same thing
If a parenthesized list contains exactly one array or hash, then all of its values are interpolated and references to each returned:
#reflist = \(#x); # Interpolate array, then get refs
#reflist = map { \$_ } #x; # Same thing
This also occurs when there are internal parentheses:
#reflist = \(#x, (#y)); # But only single aggregates expand
#reflist = (\#x, map { \$_ } #y); # Same thing
If you try this with a hash, the result will contain references to the values (as you’d expect), but references to copies of the keys (as you might not expect).
Because array and hash slices are really just lists, you can backslash a slice of either of these to get a list of references. Each of the next four lines does exactly the same thing:
#envrefs = \#ENV{"HOME", "TERM"}; # Backslashing a slice
#envrefs = \#ENV{ qw<HOME TERM> }; # Backslashing a slice
#envrefs = \( $ENV{HOME}, $ENV{TERM} ); # Backslashing a list
#envrefs = ( \$ENV{HOME}, \$ENV{TERM} ); # A list of two references
Since functions can return lists, you can apply a backslash to them. If you have more than one function to call, first interpolate each function’s return values into a larger list and then backslash the whole thing:
#reflist = \fx();
#reflist = map { \$_ } fx(); # Same thing
#reflist = \( fx(), fy(), fz() );
#reflist = ( \fx(), \fy(), \fz() ); # Same thing
#reflist = map { \$_ } fx(), fy(), fz(); # Same thing
The backslash operator always supplies a list context to its operand, so those functions are all called in list context. If the backslash is itself in scalar context, you’ll end up with a reference to the last value of the list returned by the function:
#reflist = \localtime(); # Ref to each of nine time elements
$lastref = \localtime(); # Ref to whether it’s daylight savings time
In this regard, the backslash behaves like the named Perl list
operators, such as print, reverse, and sort, which always
supply a list context on their right no matter what might be happening on their left. As with named list operators, use an explicit scalarto force what follows into scalar context:
$dateref = \scalar localtime(); # \"Sat Nov 13 10:41:30 2010"
And now you know… the rest of the story.
(with apologies to the late Paul Harvey)
See perlop.
Unary "\" creates a reference to
whatever follows it. See perlreftut
and perlref. Do not confuse this
behavior with the behavior of
backslash within a string, although
both forms do convey the notion of
protecting the next thing from
interpolation.
The Perl documentation is great and thorough, use it early and often. May I recommend perldoc perlreftut, the perl references tutorial, or perldoc perlref for more. Afterwards perldoc perlintro and perldoc perltoc or perldoc perl to see where to go from there.
And yes it creates a reference to the variable $a and stores it in the variable $ra.
It creates a reference to the variable on the right hand side; kind of like a pointer in C (without the pointer arithmetic) or a pointer in Java.
See perldoc perlref for a lot more information on the subject.
Dereferentiation is done via $$a for scalars, #$a for arrays, etc.
Iam a perl newbie and need help in understanding the below piece of code.
I have a perl Hash defined like this
1 my %myFavourite = ("Apple"=>"Apple");
2 my #fruits = ("Apple", "Orange", "Grape");
3 #myFavourite{#fruits}; # This returns Apple. But how?
It would be great if perl gurus could explain what's going on in Line-3 of the above code.
myFavourite is declared has a hash,but used as an array? And the statement simply takes the key of the hash ,greps it in to the array and returns the hash values corresponding the key searched. Is this the way we grep Hash Keys in to the Array?
It doesn't return Apple. It evaluates to a hash slice consisting of all of the values in the hash corresponding to the keys in #fruits. Notice if you turn on warnings that you get 2 warnings about uninitialized values. This is because myFavourite does not contain values for the keys Orange and Grape. Look up 'hash slice' in perldata.
Essentially, #myFavourite{#fruits} is shorthand for ($myFavourite{Apple}, $myFavourite{Orange}, $myFavourite{Grape}), which in this case is ($myFavourite{Apple},undef,undef). If you print it, the only output you see is Apple.
myFavourite is declared has a hash,but used as an array?
Yes, and it returns a list. It's a hash slice. See: http://perldoc.perl.org/perldata.html
Think of it as an expansion of array #fruits into multiple hash key lookups.
The #hash{#keys} syntax is just a handy way of extracting portions of the hash.
Specifically:
#myFavourite{#fruits}
is equivalent to:
($myFavourite{'Apple'},$myFavourite{'Orange'},$myFavourite{'Grape'})
which returns a three item list if called in list context or a concatenation of all three elements in scalar context (e.g. print)
my #slice_values = #myFavourite{#fruits}
# #slice_values now contains ('Apple',undef,undef)
# which is functionally equivalent to:
my #slice_values = map { $myFavourite{$_} } #fruits;
If you want to only extract hash values with keys, do:
my #favourite_fruits = #myFavourite{ grep { exists $myFavourite{$_} } #fruits };
# #favourite_fruits now contains ('Apple')
If you:
use warnings;
you'll see the interpreters warnings about the two uninitialized values being autovivified as undef.
Does any 1 have any idea what is $; (first split function argument) in the following code snippet:
local(#a) = ();
local($i) = 0;
for ($i = 0; $i < $d; $i++) {
#a = split($;, #b[$i]);
$c = #a[0];
}
The scalar is not found any where in the script other than in the for loop.
Any help is appreciated.
Perl's special variables are documented in perlvar, including $;
$SUBSEP
$;
The subscript separator for multidimensional array emulation. If you refer to a hash element as
$foo{$a,$b,$c}
it really means
$foo{join($;, $a, $b, $c)}
But don't put
#foo{$a,$b,$c} # a slice--note the #
which means
($foo{$a},$foo{$b},$foo{$c})
Default is "\034", the same as SUBSEP in awk. If your keys contain binary data there might not be any safe value for $;. (Mnemonic: comma (the syntactic subscript separator) is a semi-semicolon. Yeah, I know, it's pretty lame, but $, is already taken for something more important.)
Consider using "real" multidimensional arrays as described in perllol.
We could guess about why it's being used (e.g., maybe #b contains some hash's keys), but knowing how #b is created would let us provide more helpful answers.
Note also that #b[$i] and #a[0] should probably be
$b[$i]
and
$a[0]
instead. With the leading #, they're single-element array slices, but with $, they're simple scalars.
The Perl special variables are listed in perlvar.