I publish Perl stories on this blog once a week, and it seems every time there’s at least one response on social media that amounts to, “I hate Perl because of its weird syntax.” Or, “It looks like line noise.” (Perl seems to have outlasted that one—when’s the last time you used an acoustic modem?) Or the quote attributed to Keith Bostic: “The only language that looks the same before and after RSA encryption.”
So let’s address, confront, and demystify this hate. What are these objectionable syntactical, noisy, possibly encrypted bits? And why does Perl have them?
Regular expressions
Regular expressions, or regexps, are not unique to Perl. JavaScript has them. Java has them. Python has them as well as another module that adds even more features. It’s hard to find a language that doesn’t have them, either natively or through the use of a library. It’s common to want to search text using some kind of pattern, and regexps provide a fairly standardized if terse mini-language for doing so. There’s even a C‑based library called PCRE, or “Perl Compatible Regular Expressions,” enabling many other pieces of software to embed a regexp engine that’s inspired by (though not quite compatible) with Perl’s syntax.
All this is to say that Perl regular expressions can be some of the most readable and robust when used to their full potential. Early on this helped cement Perl’s reputation as a text-processing powerhouse, though the core of regexps’ succinct syntax can result in difficult-to-read code. Such inscrutable examples can be found in any language that implements regular expressions; at least Perl offers the enhancements mentioned above.
Sigils
Perl has three built-in data types that enable you to build all other data structures no matter how complex. Its variable names are always preceded by a sigil, which is just a fancy term for a symbol or punctuation mark.
A scalar contains a string of characters, a number, or a reference to something, and is preceded with a $ (dollar sign).
An array is an ordered list of scalars beginning with an element numbered 0 and is preceded with a @ (at sign).
A hash, or associative array, is an unordered collection of scalars indexed by string keys and is preceded with a % (percent sign).
So variable names $look@like%this. Individual elements of arrays or hashes are scalars, so they $look[0]$like{'this'}. (That’s the first element of the @look array counting from zero, and the element in the %like hash with a key of 'this'.)
Perl also has a concept of slices, or selected parts of an array or hash. A slice of an array looks like @this[1, 2, 3], and a slice of a hash looks like @that{'one', 'two', 'three'}. You could write it out long-hand like ($this[1], $this[2], $this[3]) and ($that{'one'}, $that{'two'}, $that{'three'} but slices are much easier. Plus you can even specify one or more ranges of elements with the .. operator, so @this[0 .. 9] would give you the first ten elements of @this, or @this[0 .. 4, 6 .. 9] would give you nine with the one at index 5 missing. Handy, that.
In other words, the sigil always tells you what you’re going to get. If it’s a single scalar value, it’s preceded with a $; if it’s a list of values, it’s preceded with a @; and if it’s a hash of key-value pairs, it’s preceded with a %. You never have to be confused about the contents of a variable because the name will tell you what’s inside.
Data structures, anonymous values, and dereferencing
I mentioned earlier that you can build complex data structures from Perl’s three built-in data types. Constructing them without a lot of intermediate variables requires you to use things like:
lists, denoted between ( parentheses )
anonymous arrays, denoted between [ square brackets ]
and anonymous hashes, denoted between { curly braces }.
Given these tools you could build, say, a scalar referencing an array of street addresses, each address being an anonymous hash:
(The => is just a way to show correspondence between a hash key and its value, and is just a funny way to write a comma (,). And like some other programming languages, it’s OK to have trailing commas in a list as we do for the 'state' entries above; it makes it easier to add more entries later.)
Although I’ve nicely spaced out my example above, you can imagine a less sociable developer might cram everything together without any spaces or newlines. Further, to extract a specific value from this structure this same person might write the following, making you count dollar signs one after another while reading right-to-left then left-to-right:
We don’t have to do that, though; we can use arrows that look like -> to dereference our array and hash elements:
say $addresses->[1]->{'name'};
We can even use postfix dereferencing to pull a slice out of this structure, which is just a fancy way of saying “always reading left to right”:
Like I said above, the sigil always tells you what you’re going to get. In this case, we got:
a sliced list of values with the keys 'name' and 'city' out of…
an anonymous hash that was itself the second element (counting from zero, so index of 1) referenced in…
an anonymous array which was itself referenced by…
the scalar named $addresses.
That’s a mouthful, but complicated data structures often are. That’s why Perl provides a Data Structures Cookbook as the perldsc documentation page, a references tutorial as the perlreftut page, and finally a detailed guide to references and nested data structures as the perlref page.
Special variables
Perl was also inspired by Unix command shell languages like the Bourne shell (sh) or Bourne-again shell (bash), so it has many special variable names using punctuation. There’s @_ for the array of arguments passed to a subroutine, $$ for the process number the current program is using in the operating system, and so on. Some of these are so common in Perl programs they are written without commentary, but for the others there is always the English module, enabling you to substitute in friendly (or at least more awk-like) names.
With use English; at the top of your program, you can say:
the @{^CAPTURE} array instead of the numbered regular expression capture variables like $1, $2, and $3
et cetera.
All of these predefined variables, punctuation and English names alike, are documented on the perlvar documentation page.
The choice to use punctuation variables or their English equivalents is up to the developer, and some have more familiarity with and assume their readers understand the punctuation variety. Other less-friendly developers engage in “code golf,” attempting to express their programs in as few keystrokes as possible.
It’s easy to hate what you don’t understand. I hope that reading this article has helped you decipher some of Perl’s “noisy” quirks as well as its features for increased readability. Let me know in the comments if you’re having trouble grasping any other aspects of the language or its ecosystem, and I’ll do my best to address them in future posts.
Related
10 thoughts on “The four noisy horsemen of Perl hate”
I learnt perl this weekend, glad I did, awesome language, and like the beautiful c++ you can choose to use what u want, I like it terse, no fan of OO, and perl’s OO reminds of the mess OO is in R, easy to avoid, in c++ and perl …
Loading…
[…] The four noisy horsemen of Perl hate […]
Loading…
I love the article and have always had love in my heart for Perl. I took many years off from the language and have just recently started to reanimate some code from 10+ years ago.
It still works great with just a minor change to allow using files in the local directory.
Loading…
I started learning code at try to use UNIX server, so when I first read perl, it seems like naturally. in bash: a=42; echo $a;
in perl: $a = 42; print $a;
more congruence
Loading…
Very nice article. Thank you!
It made me think about other Perl features that contribute to make it a delight to program in. The following ones are the first that popped out of my head.
The fact that regular expressions are first class citizens in the language make it much more inviting to use them compared with other languages in which one has to include a module and be verbosely explicit about regex compilation, group matching extraction, and what not.
It may seem counter-intuitive, but the fact that most of the built-in functions and operators act implicitly on the topic variables ($_and @_) makes for more succinct and readable code (https://blog.gnustavo.com/2020/11/perl-is-dead-expressive.html).
So many powerful built-ins (e.g. <>, map, grep, sort, join)…
Loading…
[…] ← The four noisy horsemen of Perl hate […]
Loading…
[…] Last week’s article got a great response on Hacker News, and this particular comment caught my eye: […]
Loading…
[…] 272021 Last week’s article got a great response on Hacker News, and this particular comment caught my […]
Loading…
[…] Kelsey August 5, 2021 Software & Hardware No Comments Artikel von letzter Woche habe einen gute Resonanz auf Hacker News, und diese besondere Bemerkung erregte meine […]
Loading…
[…] 052021 Last week’s article got a great response on Hacker News, and this particular comment caught my […]
Loading…
Comments are closed.
{"id":"11","mode":"button","open_style":"in_modal","currency_code":"USD","currency_symbol":"$","currency_type":"decimal","blank_flag_url":"https:\/\/phoenixtrap.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/phoenixtrap.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":500,"top_media_type":"featured_image","featured_image_url":"https:\/\/phoenixtrap.com\/wp-content\/uploads\/2021\/02\/image-200x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Leave a tip!","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"The Phoenix Trap","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"The Phoenix Trap","form_subtitle":"Do you like what you see? Leave a one-time or recurring tip!","currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for being a supporter!","payment_confirmation_title":"The Phoenix Trap","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"What is the name on your credit card?"},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"What is your email address?"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}
I learnt perl this weekend, glad I did, awesome language, and like the beautiful c++ you can choose to use what u want, I like it terse, no fan of OO, and perl’s OO reminds of the mess OO is in R, easy to avoid, in c++ and perl …
[…] The four noisy horsemen of Perl hate […]
I love the article and have always had love in my heart for Perl. I took many years off from the language and have just recently started to reanimate some code from 10+ years ago.
It still works great with just a minor change to allow using files in the local directory.
I started learning code at try to use UNIX server, so when I first read perl, it seems like naturally.
in bash:
a=42;
echo $a;
in perl:
$a = 42;
print $a;
more congruence
Very nice article. Thank you!
It made me think about other Perl features that contribute to make it a delight to program in. The following ones are the first that popped out of my head.
The fact that regular expressions are first class citizens in the language make it much more inviting to use them compared with other languages in which one has to include a module and be verbosely explicit about regex compilation, group matching extraction, and what not.
Autovivification (https://en.wikipedia.org/wiki/Autovivification) of data structures make it a breeze to work with complex data structures.
It may seem counter-intuitive, but the fact that most of the built-in functions and operators act implicitly on the topic variables ($_and @_) makes for more succinct and readable code (https://blog.gnustavo.com/2020/11/perl-is-dead-expressive.html).
So many powerful built-ins (e.g. <>, map, grep, sort, join)…
[…] ← The four noisy horsemen of Perl hate […]
[…] Last week’s article got a great response on Hacker News, and this particular comment caught my eye: […]
[…] 27 2021 Last week’s article got a great response on Hacker News, and this particular comment caught my […]
[…] Kelsey August 5, 2021 Software & Hardware No Comments Artikel von letzter Woche habe einen gute Resonanz auf Hacker News, und diese besondere Bemerkung erregte meine […]
[…] 05 2021 Last week’s article got a great response on Hacker News, and this particular comment caught my […]