
An experiment-driven guide to Perl - sea6ear
http://matt.might.net/articles/perl-by-example/
======
Mithaldu
Full disclosure: I'm the guy who made [http://perl-tutorial.org](http://perl-
tutorial.org) a few years ago because the top google result for "perl
tutorial" was a perl 4 tutorial. I have looked at many tutorials and have a
vested interest in getting quality tutorials in people's hands to avoid them
writing shitty perl.

That said, this tutorial is terrible on a number of points, since it teaches
outdated things that have long been known to be dangerous and are only kept
around for the sake of backwards compatibility. Reading it is wholly a waste
of your time, unless you already know perl like the back of your hand and wish
to get enraged; or have the masochistic desire to learn perl in a manner that
will punish both yourself and others for your mistake of reading this
tutorial.

If you truly wish to learn about Perl in a whirlwind tour, read either the
very short free book Modern Perl [1] or any other short tutorial linked on the
site i mentioned first.

If you're the author of this tutorial, i applaud you for the effort, but wish
you'd have spoken to any part of the community before publishing. If you feel
like it, #perl-help on irc.perl.org is a great place to start. And if you
meant this as a troll, 10/10, would rage anytime.

[1]
[http://onyxneon.com/books/modern_perl/](http://onyxneon.com/books/modern_perl/)

~~~
mattmight
Article author here.

To be clear, this is not a tutorial on writing good, idiomatic Perl. (And,
I've strengthened the article's disclaimers to that emphasize that.)

It's a semantic excavation of Perl.

My goal was to understand how the Perl interpreter thinks, and to answer
language design questions like: How are parameters passed--by value, by alias,
by name, by reference, by need? How are variables scoped--lexically,
dynamically, globally? What is the effect of @ in a prototype? For the ..
operator, how is the implicit toggle scoped--at the procedure or the nearest
enclosing block? How do prototypes influence context, and how do contexts
influence evaluation?

That is, I wanted to understand what was possible. The possible is entirely
separate from the good.

As a formal semanticist, I was continually surprised by how Perl behaved.

As someone that has had to occasionally debug other people's Perl, I believe
there is value in understanding the syntactic and semantic quirks in the
language.

Thanks for your comments.

I'll be updating the article with your feedback.

~~~
VLM
I can dig it. By analogy something like "If you insist on installing deck
screws with a hammer instead of a screwdriver, this is what happens with a
sledgehammer, this is what happens with a large heavy rock, this is what
happens if you use your fist..." It is interesting, rather than terrifying,
when seen in that light.

However, Google is going to google, thats its thing, so some victim in the
future might think this is the one true answer to using objects in perl, which
is not cool.

------
j_m_b
Ahh perl... the first language I used to make something non-trivial. The
coolest script I wrote was a load balancer that used ssh to submit jobs and
monitor the activity of nodes in a cluster via commands remotely executed by
ssh. No root access needed, no servers to install, just needed to have an
account accessible via ssh on the remote machine and ssh + perl on the machine
you were working on. It was the simplest solution to the complex problem of "I
have all of these computers, now how do I use them to their maximum
potential?" Stuff like Linda existed than, but I found it way too complex in
comparison to my simple scripts. Alas, I since moved onto the heady world of
lisp, but I still use perl for the occasional $ perl -pe 's/this/that/' at the
command line and as a alternative to bash scripting.

A merry Tim Toady to you all! Also, an obligatory xkcd:
[https://xkcd.com/224/](https://xkcd.com/224/)

------
maxlybbert
As a long time Perl programmer, I am a little disappointed with the lack of
comments on this post.

I generally follow Matt Might's blog, and I am impressed by previous posts.
Unfortunately, this tutorial is likely to leave beginners more confused than
when they started. I have to encourage people to look at chromatic's free book
"Modern Perl" instead.

------
theOnliest
> In Perl, there are three contexts in which an expression may be evaluated.

> 1\. scalar

> 2\. array

> 3\. void

There's actually no such thing as "array context" in Perl; instead there's
"list context". An array is a list that's been stored in a variable (this is a
fairly common mistake).

See [http://friedo.com/blog/2013/07/arrays-vs-lists-in-
perl](http://friedo.com/blog/2013/07/arrays-vs-lists-in-perl) and
[http://perlmaven.com/scalar-and-list-context-in-
perl](http://perlmaven.com/scalar-and-list-context-in-perl) for good
examples/discussion.

EDIT:

Posted this before I finished the article. Understanding the difference
between arrays and lists makes the following potential WTFs a lot clearer:

    
    
        sub take_two_arrs (\@\@) {
          print $_[0], $_[1] ;
        }
    
        take_two_arrs @a1, @b1 ;         # prints ARRAY(0xAddr) ARRAY(0xAddr)
    
        take_two_arrs ((1,2),(3,4)) ;    # error: arrays must be named
    

The second doesn't work because the prototyped function takes _array_
references, not lists. It would work if you called it like this:

    
    
        take_two_arrs ([1,2],[3,4])
      

I'll admit that this is baffling.

    
    
        sub what_are (++) {
          print $_[0], " ", $_[1] ;
        }
    
        what_are ((1,2),(3,4)) # prints 2, then 4
    

(This is part of the reason that Perl programmers don't use prototypes very
often.) perlsub warns:

> When using the + prototype, your function must check that the argument is of
> an acceptable type.

The plus here forces scalar context on the arguments, which are lists (not
arrays!), so they return their last elements. This would work how the author
probably wants if called like this:

    
    
        what_are ([1,2],[3,4]);   # prints ARRAY(0xAddr), ARRAY(0xAddr)

~~~
chromatic
_I 'll admit that this is baffling._

The inner parentheses force evaluation of the two inner comma operators in the
scalar context provided by the function prototype. `1` and `3` get evaluated
in void context and discarded, leaving `2` and `4` as the two arguments to the
function. (I had to look up `+` in prototypes, however.)

Without a working understanding of lists and context, this example is
undoubtedly baffling, but that's why the documentation exists.

~~~
theOnliest
I guess I really meant "is baffling without a thorough understanding of
context." I feel better about looking up the + now that I know you did too,
though! I don't think I've ever seen code like that in the wild, and I've
never seen a Perl programmer attempt to call a sub with nested parens, like
what_are((1,2),(3,4)) before.

~~~
perigrin
You may not realized that's what you saw, but for example all of the Moose
documentation uses effectively a nested param:

    
    
        has foo => ( is => 'ro' );
    

is equivalent to:

    
    
        has('foo', ('is', 'ro'));
    

because Moose's `has` sugar is written as a exported function.

~~~
theOnliest
That's true, but I've never actually seen anyone call 'has' like that. Plus,
Perl's behavior on lists makes sense (always flatten) if there's no mucking
around with prototypes, so that's much less confusing than the behavior in the
article.

~~~
perigrin
The first one I presented is the way the Moose documentation calls has, the
way the Moose test suite typically calls has, and the way I and most of the
rest of the Moose Cabal call has.

The second one isn't common at all, but I have seen people both completely
leave out the parentheses:

    
    
        has foo => is => 'ro', isa => 'Str', ...;
    

or treat has as a straight function

    
    
        has(foo, is => 'ro', isa => 'Str');
    

both of which cause Perl::Tidy to do weird things.

~~~
theOnliest
Sorry, I meant I'd never seen it called the second way (nested parens). I also
haven't seen the no-parens version, which looks really bizarre!

------
chromatic
The core documentation is not always clear about the difference between lists
and arrays--and much credit to the author for identifying the comma operator
as an operator--but this is really confused:

 _By default, the arguments to a procedure are in the array context, which
means that the comma operator expects both of its operands to be arrays. It
promotes them to single-element arrays if they are scalars. In Perl, comma (,)
can mean cons, append, flatten all at once._

I wrote an explanation of context in Perl which is hopefully clearer:

[http://modernperlbooks.com/books/modern_perl/chapter_01.html...](http://modernperlbooks.com/books/modern_perl/chapter_01.html#context)

------
ceronman
I loved this article.

I started writing Perl nine months ago because of my new job. I learned it
with the Modern Perl book, which is really nice and goes directly to the best
practices. However, I've found that real life Perl code is full of the
old/deprecated/insane ways of doing things as well. And Perl developers really
take the TIMTOWTDI principle to the limit.

This article helped me to understand Perl more. And specially to understand
real life Perl code better. I also liked the language designer perspective and
the semantic analysis. Thanks for writing it!

------
pasbesoin
"alarming brevity" :-)

Looking forward to reading further into this.

~~~
cbaleanu

      To accept a reference to one of several specifiers, Perl accepts a grouped \[ specifiers ] form:
      
      sub array_or_hash (\[@%]) {
        print $_[0] ;
      }
    

Dear god...

------
raiph
Hi Matt,

I've been exploring your blog. Great stuff! I was particularly appreciative of
the parsing articles.

Larry Wall (the Perl designer) has been designing and helping develop a new
language for years. (He claims he began thinking about this new language
before Perl 5 shipped 20 years ago.) Arguably it addresses the same sort of
audience as Scala and Haskell. Have you taken a look at it?

~~~
agumonkey
I can't find the link, but I remember a few talks about Perl 6 Grammars which
were very interesting both in the eDSL structure and the fact that Perl 6 was
built on top of them. I think it was Damian Conway speaking but I'm not sure
anymore.

------
slashdotaccount
I'll concentrate on the mistakes. If I were to criticise all the other many
weird formulations and expressions in this guide which make it hard to
unambiguously understand what the author meant, I would still sit and be
typing here tomorrow.

\----

> A code comment in Perl begins with a hash #

Hashes are already something different in Perl. Avoid ambiguity, use the
common name of that character: number sign.

> procedure

This word is used through-out, but the official Perl documentation does not
mention it. Use the word subroutine (or just sub for short) instead.

> The $ prefix references a variable as a scalar

> Array variables use the prefix @

This is the wrong explanation. The sigil denotes the mode of access, @
indicating the expression evaluating to a list value, $ indicating a single
value. This becomes clear when one examines slices of a compound data
structure.

    
    
        @arr = ("foo","bar","baz");
        $arr[1];    # "bar"
        @arr[2,3];  # ("bar", "baz")
    
        %hash = ("foo", 1, "bar", 2);
        $hash{"foo"};        # 1
        @hash{"foo", "bar"}; # (1, 2)
    

The guide mentions the change from @ to $ or from % to $ only in passing
without explanation, and does not mention slices at all.

> Hash variables expect an array for initialization.

No, a list.

> three contexts in which an expression may be evaluated:

> 1\. scalar

> 2\. array

> 3\. void

No, the second is list context.

> Is localtime() returning a scalar, or an array?

No, a scalar or a list.

> By default, the arguments to a procedure are in the array context, which
> means that the comma operator expects both of its operands to be arrays. It
> promotes them to single-element arrays if they are scalars.

> It seems that the function call still flattened out the arrays (and hashes)
> when making the call.

This is completely misleading. A sub takes always a list. What is described
here has nothing to do with arguments, but is the consequence of the specifics
of how values are evaluated into a list. This also happens, for example, on
list assignment.

> all of the following are equivalent procedure calls:

> print3 (1,2,3) ;

> &print3 (1,2,3) ;

This is wrong, there is a difference, it just did not show up in the example.

> In fact, the argument isn’t even hash, despite what the specifier says

Refer to the documentation: when not backslashed, % is defined to behave like
@.

> sub use_hash (%) {

> print $_[0]{"foo"} ;

> print $_{"foo"} ;

> print @_{"foo"} ;

> }

> use_hash ("foo" => 1701) ; # prints nothing

No wonder. The code is broken.

@_ contains a plain list value. To access it with a hash subscript, turn it
into a hashref first.

    
    
        print +{ @_ }->{"foo"};
        print ${ {@_} }{"foo"};
    

> The specifier & expects to receive a function

Not function, coderef is the appropriate word.

> To accept a bareword filehandle as an argument, it becomes necessary to use
> the rarely used * prototype specifier

Simply passing *F is also possible, no prototype involved.

> The repetition operator x repeats a string or an array,

No, it repeats single or list values. Scalars are coerced into their string
representation, and lists are simply repeated unchanged.

\----

Closing words: This is amateur hour, not worthy of a professor. Advice for
next time: consult domain experts and have them proof-read before publishing,
and also always give your documents a last-modification date and version
history, or at least a version identifier.

------
durrrrrrr
"Every programmer needs Perl in their arsenal."

I stopped reading at this point.

