Saturday, February 1, 2020

Constants and Variables and Operators, Oh My!

Declaring a Variable

Sigils

Every variable name in Perl is prefixed by what is known as a sigil, which denotes in very broad terms the category of data being stored by the variable. Note that I use category rather than type. The most commonly encountered sigil, $, is used for any of the scalar data types, i.e. data types that store only a single value, such as strings, integers, floating-point numbers, etc. The sigil @ is used for arrays, and the sigil % for hashes, but we won’t be working with those just yet.

Identifiers

The identifier is the part of the variable that comes after the sigil—the variable’s actual name. The identifier can consist of any combination of uppercase letters, lowercase letters, digits, and the underscore (_) character, with the sole restriction that the first character of the identifier cannot be a digit.

Scope

The first time a variable name is used, its scope must be specified. This is done by placing one of two keywords in front of the sigil and identifier. Local variables (those that persist only in the current code block) are declared using the keyword my. For example, to declare a local variable named foo and assign it the value 7, we would write my $foo = 7;. On future uses of this variable within the same code block, we would simply use the sigil and identifier by themselves, for example $foo = 5;. As soon as we exit the current code block, $foo disappears.

Global variables do not disappear at the end of the current code block, but instead persist throughout the entire program. Global variables are declared using the keyword our. So to declare a global variable named foo and assign it the value 7, we would write our $foo = 7;. As with local variables, we would use only the sigil and identifier on future uses of this variable. Because they persist throughout the program, global variables can create potential problems and should therefore be used sparingly.

Constants

Perl has no built-in construct for declaring constants—that is, variables whose values cannot be changed once they have been declared. However, variables whose values are intended not to change once they have been declared are conventionally given identifiers consisting of uppercase letters and underscores if necessary to separate words. For example, the number of centimeters in one inch might be declared as our $CM_PER_INCH = 2.54;. While Perl won’t prevent us from changing this value later, the fact that its identifier is in all caps tells us we probably shouldn’t.

As an aside, declaring global constants is not nearly as problematic as declaring global non-constant variables, since the value associated with a constant is expected to remain the same throughout the entire program.

Data Types

Numeric Data Types

Perl treats integers and floating-point numbers equally and will freely convert between them. So, from Perl’s point of view, there is no difference between 7 (integer) and 7.0 (floating-point). Perl allows the use of the underscore as a thousands separator in numeric literals, for example my $foo = 1_000.0; is the same as my $foo = 1000.0. Additionally, integers can be declared in hexadecimal by prefixing 0x, in octal by prefixing 0, and in binary by prefixing 0b. So, for example, 0x20, 040, and 0b100000 all evaluate to 32.

Strings

Strings are how Perl stores text. Strings can be delimited either by single quotes (') or double quotes ("), and the two types of strings work slightly differently.

Single-Quoted Strings

Strings delimited by single quotes are treated as raw text. Escape sequences (such as \n for newline) within a single-quoted string are not processed. For example, print 'Hello, World!\n'; produces the output Hello, World!\n. The \n is printed to the screen as-is rather than being converted to a newline character. The sole exception to this is the escape sequence \', which is used to allow the single-quote character to appear within a string delimited by single quotes.

Double-Quoted Strings

Escape sequences appearing in strings delimited by double quotes are converted into the special characters they represent. So print "Hello, World!\nMore text on the next line"; produces the output

Hello, World! More text on the next line

Additionally, double-quoted strings allow what is known as interpolation. When a variable name (complete with sigil) appears inside a string, the value of the variable is substituted into the string. So the code

my $foo = 7; print "The value of foo is $foo";

produces the output The value of foo is 7. Note that the substitution occurs immediately when the string is evaluated and will not reflect subsequent changes to the value of the variable. So the code

my $foo = 7; my $output = "The value of foo is $foo"; $foo = 12; print $output;

also produces the output The value of foo is 7, because $foo was 7 at the time the string was evaluated. The subsequent change to the value of $foo does not cause the string to be updated to reflect the new value of $foo.

Operators

Arithmetic Operators

As one might expect, +, -, *, and / are used to add, subtract, multiply, and divide numbers. Because Perl treats integers and floating-point numbers equally, the / operator always performs floating-point division, unlike in many languages where the result of dividing two integers is always an integer. Perl also includes the exponentiation operator, **, which raises the first number to the power of the second, and the modulo operator, %, which gives the remainder when the first number is divided by the second. So the code

print 24 + 7, "\n"; print 24 - 7, "\n"; print 24 * 7, "\n"; print 24 / 7, "\n"; print 24 ** 7, "\n"; print 24 % 7, "\n";

produces the output

31 17 168 3.42857142857143 4586471424 3

All of the arithmetic operators work equally well with variables as they do with numeric literals. So, for example, the code

my $foo = 24; my $bar = 7; print $foo + $bar;

produces the output 31.

Compound Assignment Operators

Any of the six arithmetic operators listed above can be prefixed to the assignment operator, =, to produce what is known as a compound assignment operator. A compound assignment operator always takes a variable as its first argument. Its second argument can be a literal or another variable. The effect of a compound assignment operator is to apply the specified arithmetic operation and then store the result back into the variable provided as the first argument. So the code

my $foo = 7; $foo **= 2; print $foo;

produces the output 49.

Increment and Decrement Operators

One of the more common cases of modifying a variable’s value and storing the result back to the same variable is adding or subtracting 1 from the variable’s value. Perl provides special operators for doing this, known as the increment (++) and decrement (--) operators. Unlike the operators discussed above, the increment and decrement operators are unary—they work on only a single value. So, for example, the code

my $foo = 24; my $bar = 7; $foo++; $bar--; print "$foo\n$bar\n";

produces the output

25 6

The increment and decrement operators can also be placed before the variable (including sigil), i.e. ++$foo;. In the most common case, where the increment or decrement occurs on a line by itself, there is no difference between the two usages.

String Operators

Perl also provides two operators whose use is specific to strings. The string concatenation operator, which puts two strings together one after the other, is . Note that this is different from many languages, which use + for this purpose as well as for addition. The reason for this is that, in Perl, a string whose contents can be interpreted as a numeric literal can be implicitly converted to a number. So, for example, the code

my $foo = "6.5"; my $bar = "27"; print $foo + $bar, "\n"; print $foo . $bar, "\n";

produces the output

33.5 6.527

Notice how, when the + operator was used, the two strings were implicitly converted to numbers and treated as if they were numbers.

The second string operator is the repetition operator, x. It takes a string as its first argument and a number as its second argument, and it repeats the given string the specified number of times (if the number given is not an integer, it is rounded down; if the number given is negative, it is treated as 0). So, for example, the code print "foo"x3; produces the output foofoofoo.

2 comments:

  1. I've never seen sigils used in any other language. I had noticed you had put "my" in front of declarations, is there a specific significance of it being there?

    ReplyDelete
    Replies
    1. "my" marks it as a local variable, as opposed to a global variable, which would be declared using the keyword "our."

      Delete