Monday, September 13, 2010

Running a perl program

Explicitly invoking the Perl compiler/interpreter
(note that >>> is prompt only)
>>>perl program.pl
Many command line options are available here eg.
-w print all warnings
-c check but do not execute
-d run under debugger control

Implicitly invoking the Perl compiler/interpreter
It is system specific. e.g. Unix
#!/usr/bin/perl
print "Please enter your name: ";
 This is popular shebang notation. Also you can do following:
#!/usr/bin/perl -w
for warning check etc like we do with command line options.

More operators in perl

x         The repetition operator. Returns a string consisting of the left operand repeated the number of times specified by the right operand. In an array context, if the left operand is a list in parens, it repeats the list.

print '-' x 80; # print row of dashes
print '-' x80; # illegal, x80 is identifier
print "\t" x ($tab/8), ' ' x ($tab%8); # tab over
@ones = (1) x 80; # an array of 80 1's
@ones = (5) x @ones; # set all elements to 5

x=        The repetition assignment operator. Only works on scalars.

..          The range operator, which is really two different operators depending on the context. In an array context, returns an array of values counting (by ones) from the left value to the right value. This is useful for writing "for (1..10)" loops and for doing slice operations on arrays.

In a scalar context, .. returns a boolean value. The operator is bistable, like a flip-flop, and emulates the line-range (comma) operator of sed, awk, and various editors. Each .. operator maintains its own boolean state. It is false as long as its left operand is false. Once the left operand is true, the range operator stays true until the right operand is true, AFTER which the range operator becomes false again. (It doesn't become false till the next time the range operator is evaluated. It can test the right operand and become false on the same evaluation it became true (as in awk), but it still returns true once. If you don't want it to test the right operand till the next evaluation (as in sed), use three dots (...) instead of two.) The right operand is not evaluated while the operator is in the "false" state, and the left operand is not evaluated while the operator is in the "true" state. The precedence is a little lower than

and &&. The value returned is either the null string for false, or a sequence number (beginning with 1) for true. The sequence number is reset for each range encountered. The final sequence number in a range has the string 'E0' appended to it, which doesn't affect its numeric value, but gives you something to search for if you want to exclude the endpoint. You can exclude the beginning point by waiting for the sequence number to be greater than 1. If either operand of scalar .. is static, that operand is implicitly compared to the $. variable, the current line number.



Examples:



As a scalar operator:

if (101 .. 200) { print; } # print 2nd hundred lines



next line if (1 .. /^$/); # skip header lines



s/^/> / if (/^$/ .. eof()); # quote body



As an array operator:

for (101 .. 200) { print; } # print $_ 100 times



@foo = @foo[$[ .. $#foo]; # an expensive no-op

@foo = @foo[$#foo-4 .. $#foo]; # slice last 5 items

More operators in perl

x         The repetition operator. Returns a string consisting of the left operand repeated the number of times specified by the right operand. In an array context, if the left operand is a list in parens, it repeats the list.

print '-' x 80; # print row of dashes
print '-' x80; # illegal, x80 is identifier
print "\t" x ($tab/8), ' ' x ($tab%8); # tab over
@ones = (1) x 80; # an array of 80 1's
@ones = (5) x @ones; # set all elements to 5

x=        The repetition assignment operator. Only works on scalars.

..          The range operator, which is really two different operators depending on the context. In an array context, returns an array of values counting (by ones) from the left value to the right value. This is useful for writing "for (1..10)" loops and for doing slice operations on arrays.

In a scalar context, .. returns a boolean value. The operator is bistable, like a flip-flop, and emulates the line-range (comma) operator of sed, awk, and various editors. Each .. operator maintains its own boolean state. It is false as long as its left operand is false. Once the left operand is true, the range operator stays true until the right operand is true, AFTER which the range operator becomes false again. (It doesn't become false till the next time the range operator is evaluated. It can test the right operand and become false on the same evaluation it became true (as in awk), but it still returns true once. If you don't want it to test the right operand till the next evaluation (as in sed), use three dots (...) instead of two.) The right operand is not evaluated while the operator is in the "false" state, and the left operand is not evaluated while the operator is in the "true" state. The precedence is a little lower than

and &&. The value returned is either the null string for false, or a sequence number (beginning with 1) for true. The sequence number is reset for each range encountered. The final sequence number in a range has the string 'E0' appended to it, which doesn't affect its numeric value, but gives you something to search for if you want to exclude the endpoint. You can exclude the beginning point by waiting for the sequence number to be greater than 1. If either operand of scalar .. is static, that operand is implicitly compared to the $. variable, the current line number.



Examples:



As a scalar operator:

if (101 .. 200) { print; } # print 2nd hundred lines



next line if (1 .. /^$/); # skip header lines



s/^/> / if (/^$/ .. eof()); # quote body



As an array operator:

for (101 .. 200) { print; } # print $_ 100 times



@foo = @foo[$[ .. $#foo]; # an expensive no-op

@foo = @foo[$#foo-4 .. $#foo]; # slice last 5 items

Comparison operators in perl


cmp --String comparison, returning -1, 0, or 1.
<=>    Numeric comparison, returning -1, 0, or 1. (looks like flying saucer)

 =~       Certain operations search or modify the string "$_" by default. This operator makes that kind of operation work on some other string. The right argument is a search pattern, substitution, or translation. The left argument is what is supposed to be searched, substituted, or translated instead of the default "$_". The return value indicates the success of the operation. (If the right argument is an expression other than a search pattern, substitution, or translation, it is interpreted as a search pattern at run time. This is less efficient than an explicit search, since the pattern must be compiled every time the expression is evaluated.) The precedence of this operator is lower than unary minus and autoincrement/decrement, but higher than everything else.


!~       Just like =~ except the return value is negated.

Operators in perl - bitwise operators

Bitwise operators
>> - Bitwise shift shifting the bits in the left operand to the right by the number of bits indicated by the right operand.


<< - Bitwise shift shifting the bits in the left operand to the left by the number of bits indicated by the right operand.

~ - Ones complement

Operators in perl - relational operators

Note eq is for string and == is for integers. So here are operator for int and corresponding operator for strings.


Comparison Numeric String
Equal == eq
Not equal != ne
Greater than > gt
Less than < lt
Greater than or equal to >= ge
Less than or equal to <= le

Logical operators
 &&,and
||      or

Logical expression
The next few structures rely on a test being true or false. In Perl any non-zero number and non-empty string is counted as true. The number zero, zero by itself in a string, and the empty string are counted as false. Here are some tests on numbers and strings.

$a == $b                # Is $a numerically equal to $b?
# Beware: Don't use the = operator.
$a != $b # Is $a numerically unequal to $b?
$a eq $b # Is $a string-equal to $b?
$a ne $b # Is $a string-unequal to $b?


You can also use logical and, or and not:

($a && $b)              # Is $a and $b true?
($a || $b) # Is either $a or $b true?
!($a) # is $a false?

Note that perl is loosely typed language and allows you anything..which you do with
int etc to do with strings. So here is one eg.
So far we have been testing numbers, but there is more to life than numbers. There are strings too, and these need testing too.
$name  = 'Mark';

$goodguy = 'Tony';

if ($name == $goodguy) {
print "Hello, Sir.\n";
} else {
print "Begone, evil peon!\n";
}
Something seems to have gone wrong here. Obviously Mark is different to Tony, so why does perl consider them equal?
Mark and Tony are equal -- numerically. We should be testing them as strings, not as numbers. To do this, simply substitute == for eq and everything will work as expected.

Understanding 0 in perl

There are many Perl functions which test for Truth. Some are if, while, unless . So it is important you know what truth is, as defined by Perl, not your tax forms. There are three main rules:
  1. Any string is true except for "" and "0".
  2. Any number is true except for 0. This includes negative numbers.
  3. Any undefined variable is false. A undefined variable is one which doesn't have a value, ie has not been assigned to.
Some example code to illustrate the point:
&isit;                   # $test1 is at this moment undefined

$test1="hello"; # a string, not equal to "" or "0"
&isit;

$test1=0.0; # $test1 is now a number, effectively 0
&isit;

$test1="0.0"; # $test1 is a string, but NOT effectively 0 !
&isit;

sub isit {
if ($test1) { # tests $test1 for truth or not
print "$test1 is true\n";
} else { # else statement if it is not true
print "$test1 is false\n";
}
}


The first test fails because $test1 is undefined. This means it has not been created by
assigning a value to it. So according to Rule 3 it is false. The last two tests are
interesting. Of course, 0.0 is the same as 0 in a numeric context. But it is not the
same as 0 in a string context, so in that case it is true.
So here we are testing single variables. What's more useful is testing the result of an expression. For example, this is an expression; $x * 2 and so is this; $var1 + $var2 . It is the end result of these expressions that is evaluated for truth.
An example demonstrates the point:
$x=5;
$y=5;

if ($x - $y) {
print '$x - $y is ',$x-$y," which is true\n";
} else {
print '$x - $y is ',$x-$y," which is false\n";
}
The test fails because 5-5 of course is 0, which is false. The print statement might look a little strange. Remember that print is a list operator? So we hand it a list. First item, a single-quoted string. It is single quoted because it we do not want to perform variable interpolation on it. Next item is an expression which is evaluated, and the result printed. Finally, a double-quoted string is used because we want to print a newline, and without the doublequotes the \n won't be interpolated.
What is probably more useful than testing a specific variable for truth is equality testing. For example, has your lucky number been drawn?
$lucky=15;
$drawnum=15;

if ($lucky == $drawnum) {
print "Congratulations!\n";
} else {
print "Guess who hasn't won!\n";
}
The important point about the above code is the equality operator, == .