Why is $ split valid syntax? [duplicate] - perl

I just discovered that perl ignores space between the sigil and its variable name and was wondering if someone could tell me if this was the expected behaviour. I've never run into this before and it can result in strange behaviour inside of strings.
For example, in the following code, $bar will end up with the value 'foo':
my $foo = 'foo';
my $bar = "$ foo";
This also works with variable declarations:
my $
bar = "foo\n";
print $bar;
The second case doesn't really matter much to me but in the case of string interpolation this can lead to very confusing behaviour. Anyone know anything about this?

Yes, it is part of the language. No, you should not use it for serious code. As for being confusing in interpolation, all dollar signs (that are not part of a variable) should be escaped, not just the ones next to letters, so it shouldn't be a problem.
I do not know if this is the real reason behind allowing whitespace in between the sigil and the variable name, but it allows you to do things like
my $ count = 0;
my $file_handle_foo = IO::File->new;
which might be seen by some people as handy (since it puts the sigils and the unique parts of the variable names next to each other). It is also useful for Obfu (see the end of line 9 and beginning of line 10):
#!/usr/bin/perl -w # camel code
use strict;
$_='ev
al("seek\040D
ATA,0, 0;");foreach(1..3)
{<DATA>;}my #camel1hump;my$camel;
my$Camel ;while( <DATA>){$_=sprintf("%-6
9s",$_);my#dromedary 1=split(//);if(defined($
_=<DATA>)){#camel1hum p=split(//);}while(#dromeda
ry1){my$camel1hump=0 ;my$CAMEL=3;if(defined($_=shif
t(#dromedary1 ))&&/\S/){$camel1hump+=1<<$CAMEL;}
$CAMEL--;if(d efined($_=shift(#dromedary1))&&/\S/){
$camel1hump+=1 <<$CAMEL;}$CAMEL--;if(defined($_=shift(
#camel1hump))&&/\S/){$camel1hump+=1<<$CAMEL;}$CAMEL--;if(
defined($_=shift(#camel1hump))&&/\S/){$camel1hump+=1<<$CAME
L;;}$camel.=(split(//,"\040..m`{/J\047\134}L^7FX"))[$camel1h
ump];}$camel.="\n";}#camel1hump=split(/\n/,$camel);foreach(#
camel1hump){chomp;$Camel=$_;y/LJF7\173\175`\047/\061\062\063\
064\065\066\067\070/;y/12345678/JL7F\175\173\047`/;$_=reverse;
print"$_\040$Camel\n";}foreach(#camel1hump){chomp;$Camel=$_;y
/LJF7\173\175`\047/12345678/;y/12345678/JL7F\175\173\0 47`/;
$_=reverse;print"\040$_$Camel\n";}';;s/\s*//g;;eval; eval
("seek\040DATA,0,0;");undef$/;$_=<DATA>;s/\s*//g;( );;s
;^.*_;;;map{eval"print\"$_\"";}/.{4}/g; __DATA__ \124
\1 50\145\040\165\163\145\040\157\1 46\040\1 41\0
40\143\141 \155\145\1 54\040\1 51\155\ 141
\147\145\0 40\151\156 \040\141 \163\16 3\
157\143\ 151\141\16 4\151\1 57\156
\040\167 \151\164\1 50\040\ 120\1
45\162\ 154\040\15 1\163\ 040\14
1\040\1 64\162\1 41\144 \145\
155\14 1\162\ 153\04 0\157
\146\ 040\11 7\047\ 122\1
45\15 1\154\1 54\171 \040
\046\ 012\101\16 3\16
3\15 7\143\15 1\14
1\16 4\145\163 \054
\040 \111\156\14 3\056
\040\ 125\163\145\14 4\040\
167\1 51\164\1 50\0 40\160\
145\162 \155\151
\163\163 \151\1
57\156\056

Related

Perl comparison operator output

I am not exactly sure what the output of a comparison is. For instance, consider
$rr = 1>2;
$qq = 2>1;
print $rr; #nothing printed
print $qq; #1 printed
Is $rr the empty string? Is this behavior documented somewhere? Or how can one tell for sure?
I was looking for the answer in Learning Perl by Schwartz et al., but could not immediately resolve the answer.
http://perldoc.perl.org/perlop.html#Relational-Operators:
Perl operators that return true or false generally return values that can be safely used as numbers. For example, the relational operators in this section and the equality operators in the next one return 1 for true and a special version of the defined empty string, "" , which counts as a zero but is exempt from warnings about improper numeric conversions, just as "0 but true" is.
So it what is returned is something that is an empty string in string context, and 0 in numeric context.

What does this mean in Perl 1..$#something?

I have a loop for example :
for my $something ( #place[1..$#thing] ) {
}
I don't get this statement 1..$#thing
I know that # is for comments but my IDE doesn't color #thing as comment. Or is it really just a comment for someone to know that what is in "$" is "thing" ? And if it's a comment why was the rest of the line not commented out like ] ) { ?
If it has other meanings, i will like to know. Sorry if my question sounds odd, i am just new to perl and perplexed by such an expression.
The $# is the syntax for getting the highest index of the array in question, so $#thing is the highest index of the array #thing. This is documented in perldoc perldata
.. is the range operator, and 1 .. $#thing means a list of numbers, from 1 to whatever the highest index of #thing is.
Using this list inside array brackets with the # sigill denotes that this is an array slice, which is to say, a selected number of elements in the #place array.
So assuming the following:
my #thing = qw(foo bar baz);
my #place = qw(home work restaurant gym);
then #place[1 .. $#thing] (or 1 .. 2) would expand into the list work, restaurant.
It is correct that # is used for comments, but not in this case.
it's how you define a range. From starting value to some other value.
for my $something ( #place[1..3] ) {
# Takes the first three elements
}
Binary ".." is the range operator, which is really two different
operators depending on the context. In list context, it returns a list
of values counting (up by ones) from the left value to the right
value. If the left value is greater than the right value then it
returns the empty list. The range operator is useful for writing
foreach (1..10) loops and for doing slice operations on arrays. In the
current implementation, no temporary array is created when the range
operator is used as the expression in foreach loops, but older
versions of Perl might burn a lot of memory when you write something
like this:
http://perldoc.perl.org/perlop.html#Range-Operators

When does Perl impose string context?

It appears that string context (while a real thing, and mentioned in "Programming Perl" chapter "2.7.1. Scalar and List Context" as a sub-idea of scalar context), isn't clearly documented anywhere I was able to find on Perldoc.
Obviously, some things in Perl (e.g. eq operator, or qq// quoting interpolation) force a value into a string context.
When does Perl impose string context?
perldoc seems to contain no useful answer.
Perl will vivify the PV (the string component) of the structure that comprises a scalar when Perl needs a string. The best place to learn about this is in perlguts, perldata, and to a lesser degree, perlop. But essentially any time a string type operation is performed with a scalar, it will impose your sense of string context, and if the scalar only contains, for example, an integer, a string will be implicitly created from that value.
So, if you have $var = 15, which places an integer in $var, and then say, if( $var eq '15' ) {...}, a string representation of the integer 15 will be generated and stored in the PV portion of the scalar's struct.
This is by no means a complete list, but the following will do the trick:
String comparison operators (eq, ne, ge, le, lt, gt)
Match binding operators for left operand (=~, !~)
string interpolation (qq{$var} , "$var", qx/$var/, and backticks)
Regex operators (m/$interpolated/, s/$interpolated//, qr/$interpolated/)
<<"HERE" (HERE doc with interpolation)
Hash key $hash{$stringified_key}.
. concatenation operator.
In newer versions of Perl, with the bitwise feature enabled, the string bitwise operators &., |., ^., and ~., along with their assignment counterparts such as &.= will invoke string context on their operands.
vec imposes string context on its first parameter.
There probably are others. But the good news is that this implementation detail rarely leaks to abstraction layers outside of the "guts" level. One example of where it can be a concern is when encoding JSON, since the JSON modules I am familiar with all look at whether or not a given scalar has a PV component to decide whether to encode a value as a string or a number.
As Joel identified in a comment below, the Devel::Peek module, which has been in the Perl core since Perl version 5.6.0 can facilitate introspection into the guts of a scalar:
use Devel::Peek;
my $foo = 12;
print "Initial state of \$foo:\n";
Dump($foo);
my $bar = "$foo";
print "\n\nFinal state of \$foo:\n";
Dump($foo);
The output produced by that code is:
Initial state of $foo:
SV = IV(0x56547b4bb2a0) at 0x56547b4bb2b0
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 12
Final state of $foo:
SV = PVIV(0x56547b4b5880) at 0x56547b4bb2b0
REFCNT = 1
FLAGS = (IOK,POK,pIOK,pPOK)
IV = 12
PV = 0x56547b4ab600 "12"\0
CUR = 2
LEN = 10
As you can see, after the forced stringification there is a PV element, the POK flag is set, and the CUR and LEN fields are present to indicate the string buffer's length and the current length of its contents.

What does #data actually contain in PDF::Report::Table $table_write->addTable(#data);?

I think I've got the gist of creating a table using Perl's PDF::Report and PDF::Report::Table, but am having difficulty seeing what the 2-dimensional array #data would look like.
The documentation says it's a 2-dimensional array, but the example on CPAN just shows an array of arrays test1, test2, and so on, rather than the example showing data and formatting like $padding $bgcolor_odd, and so on.
Here's what I've done so far:
$main_rpt_path = "/home/ics/work/rpts/interim/mtr_prebill.rpt";
$main_rpt_pdf =
new PDF::Report('PageSize' => 'letter', 'PageOrientation' => 'Landscape',);
$main_rpt_tbl_wrt =
PDF::Report::Table->new($main_rpt_pdf);
Obviously, I can't pass a one dimensional array, but I have searched for examples and can only find the one in CPAN search.
Edit:
Here is how I am trying to call addTable:
$main_rpt_tbl_wrt->addTable(build_table_writer_array($pt_column_headers_ref, undef));
.
.
.
sub build_table_writer_array
# $data -- an array ref of data
# $format -- an array ref of formatting
#
# returns an array ref of a 2d array.
#
{
my ($data, $format) = #_;
my $out_data_table = undef;
my #format_array = (10, 10, 0xFFFFFF, 0xFFFFCC);
$out_data_table = [[#$data],];
return $out_data_table;
}
and here is the error I'm getting.
Use of uninitialized value in subtraction (-) at /usr/local/share/perl5/PDF/Report/Table.pm line 88.
at /usr/local/share/perl5/PDF/Report/Table.pm line 88
I cannot figure out what addTable wants for data. That is I am wondering where the formatting is supposed to go.
Edit:
It appears the addData call should look like
$main_rpt_tbl_wrt->addTable(build_table_writer_array($pt_column_headers_ref), 10,10,xFFFFFF, 0xFFFFCC);
not the way I've indicated.
This looks like a bug in the module. I tried running the example code in the SYNOPSIS, and I got the same error you get. The module has no real tests, so it is no surprise that there would be bugs. You can report it on CPAN.
The POD has bugs, too.
You increase your chances of getting it fixed if you look at the source code and fix it yourself with a patch.

How do you concatenate strings in a Puppet .pp file?

Here is my naive approach:
# puppet/init.pp
$x = 'hello ' +
'goodbye'
This does not work. How does one concatenate strings in Puppet?
Keyword variable interpolation:
$value = "${one}${two}"
Source: http://docs.puppetlabs.com/puppet/4.3/reference/lang_variables.html#interpolation
Note that although it might work without the curly braces, you should always use them.
I use the construct where I put the values into an array an then 'join' them.
In this example my input is an array and after those have been joined with the ':2181,' the resulting value is again put into an array that is joined with an empty string as separator.
$zookeeperservers = [ 'node1.example.com', 'node2.example.com', 'node3.example.com' ]
$mesosZK = join([ "zk://" , join($zookeeperservers,':2181,') ,":2181/mesos" ],'')
resulting value of $mesosZK
zk://node1.example.com:2181,node2.example.com:2181,node3.example.com:2181/mesos
Another option not mentioned in other answers is using Puppet's sprintf() function, which functions identically to the Ruby function behind it. An example:
$x = sprintf('hello user %s', 'CoolUser')
Verified to work perfectly with puppet. As mentioned by chutz, this approach can also help you concatenate the output of functions.
The following worked for me.
puppet apply -e ' $y = "Hello" $z = "world" $x = "$y $z" notify { "$x": } '
notice: Hello world
notice: /Stage[main]//Notify[Hello world]/message: defined 'message' as 'Hello world'
notice: Finished catalog run in 0.04 seconds
The following works as well:
$abc = "def"
file { "/tmp/$abc":
You could use the join() function from puppetlabs-stdlib. I was thinking there should be a string concat function there, but I don't see it. It'd be easy to write one.
As stated in docs, you can just use ${varname} interpolation. And that works with function calls as well:
$mesosZK = "zk://${join($zookeeperservers,':2181,')}:2181/mesos"
$x = "${dirname($file)}/anotherfile"
Could not use {} with function arguments though: got Syntax error at '}'.