2 <html><head><meta charset=
"utf-8"><title>Level up your Perl
</title><link rel=
"stylesheet" href=
"css/common.css"><link rel=
"stylesheet" href=
"css/slides.css"></head><body><textarea id=
"source">
12 - Hi. I'm Charles McGarvey.
13 - Been a Perl programmer for a long time...
18 ![The Raptor](img/raptor.png)
21 - Deciding what to talk on... everything!
22 - List of things that you should know or be aware of...
23 - This image works well (merit badge)...
29 ![Endurance](img/endurance.png)
31 ### https://jobs.endurance.com/bluehost
34 - My employer is hiring.
35 - It's a pretty cool employer...
40 ## Use [`B::Deparse`](https://metacpan.org/pod/B::Deparse).
43 - `B::Deparse` is a backend module for the compiler.
44 - It takes the parse tree after compiling and generates Perl code from it.
46 So, why compile Perl only to turn it back into Perl?
47 It is useful for checking that perl and you are both understanding the code the same way.
52 ## Example of `B::Deparse`.
55 perl -MO=Deparse,-p -e'$a && not $b && not $c'
56 *($a and not(($b && (!$c))));
62 perl -MO=Deparse,-p -e'$a && ! $b && ! $c'
63 *(($a and not($b)) and not($c));
68 - These example snippets demonstrate an actual bug found in real code.
70 - The first snippet is mixing high and low-precedence logical operators. Comparing the output of Deparse, it's fairly
71 clear to see that these are not doing the same thing.
73 - Deparse supports other flags that may be useful. Read the pod to find out more.
75 - Aside: Be careful about mixing high and low-precedence logical operators.
80 ## Know regular expressions.
83 - Like, really know them.
84 - I meet a lot of people who don't know regexp.
93 - All you have to do in order to read and write regular expressions *without looking at a help resource every time* is
94 know a few basic things.
101 # (what to match) (how many to match)
104 - Regular expressions let you match strings.
105 - Find out "does a string follow a specific pattern".
108 ### What to match: Literals
110 - Match a specific character
119 ### What to match: Character classes
121 - Match a character within a set
131 ### How many to match: Quantifiers
133 - Match a certain number of the preceding single character or character class
141 class: center, middle
143 # (what to match) (how many to match)
149 class: center, middle
151 ## Okay, there is more...
154 - But if you know just those concepts, you can already read a large number of regexp that you'll come across.
159 - Look for the edges surrounding or between things
163 - `\b{sb}` - sentence boundary
167 I say "look for" instead of "match" because the boundary isn't something that shows up in the results.
178 - Separate the regexp into logical chunks
180 - `(?:whatever)` - noncapturing
185 - Match something again
193 - Require presence of something without actually matching it
194 - `(?=regexp)` and `(?!regexp)` - lookahead
195 - `(?<=regexp)` and `(?
<!regexp)` - lookbehind
198 These are zero-length assertions. Like boundaries, these don't actually match anything; they just make sure something is
199 or isn't present at the position where it exists relative to its surroundings.
202 class: center, middle
204 ## Use [`Regexp::Debugger`](https://metacpan.org/pod/Regexp::Debugger).
207 class: ex-regexpdebugger
210 use Regexp::Debugger;
212 my $not_png_or_jpg = qr/(?<!\.(png|jpg))$/;
213 my $filename = 'log.txt';
215 $filename =~ $not_png_or_jpg;
219 class: ex-regexpdebugger
222 *use Regexp::Debugger;
224 my $not_png_or_jpg = qr/(?<!\.(png|jpg))$/;
225 my $filename = 'log.txt';
227 $filename =~ $not_png_or_jpg;
231 ![Regexp::Debugger in action](img/regexp_debugger.png)
234 class: regexpdebugger-commands
236 ## Things you can do with Regexp::Debugger
239 - The basics: step forward (
"s") and backwards (
"-").
242 - Hit
"d" to get a detailed description of the regexp:
245 (?<! Match negative lookbehind
246 \. Match a literal '.' character
247 ( The start of a capturing block ($
1)
248 png Match a literal sequence (
"png")
250 jpg Match a literal sequence (
"jpg")
252 ) The end of negative lookbehind
253 $ Match only if at end of string (or final newline)
257 - Try different modes, like
"e" for event log.
263 - Hit
"q" to exit the debugger.
266 class: center, middle
268 ### Also, check out [PPR](https://metacpan.org/pod/PPR).
271 This module was brought to us by Damian Conway. Speaking of, if your interest in regular expressions continues, check
272 out this module. `PPR` is a packaged regular expression with subpatterns that can match Perl code.
277 class: center, middle
279 ## Write Vim plugins in Perl.
282 class: center, middle
287 class: ex-vimcheck, center, middle
289 ### Does your Vim support Perl?
292 vim --version |grep +perl && echo 'Aww yeah!'
296 Some minimal builds of Vim do not have Perl support compiled in.
300 class: ex-vimcheck, center, middle
302 ### You'll need this...
308 Chapter
41 in the Vim manual is all about scripting.
314 function! color#random()
315 let l:colorlist = globpath(&rtp,
"colors/*.vim")
317 my ($result, $colors) = VIM::Eval(
"l:colorlist");
318 return if $result !=
1;
319 my @available_colors = split(/\n/, $colors);
320 my %bad_colors = eval {
321 open(my $fh, '<',
"$ENV{HOME}/.vim/color_blacklist.txt");
322 map { chomp; ($_ =
> 1) } <$fh
>;
324 for (my $tries =
0; $tries <
100; ++$tries) {
325 my $colorpath = $available_colors[int(rand(@available_colors))];
326 my ($color) = $colorpath =~ m!([^/]+)\.vim!;
327 if (!$bad_colors{$color}) {
328 VIM::DoCommand("colorscheme $color");
340 *function! color#random()
341 * let l:colorlist = globpath(&rtp, "colors/*.vim")
343 my ($result, $colors) = VIM::Eval(
"l:colorlist");
344 return if $result !=
1;
345 my @available_colors = split(/\n/, $colors);
346 my %bad_colors = eval {
347 open(my $fh, '<',
"$ENV{HOME}/.vim/color_blacklist.txt");
348 map { chomp; ($_ =
> 1) } <$fh
>;
350 for (my $tries =
0; $tries <
100; ++$tries) {
351 my $colorpath = $available_colors[int(rand(@available_colors))];
352 my ($color) = $colorpath =~ m!([^/]+)\.vim!;
353 if (!$bad_colors{$color}) {
354 VIM::DoCommand("colorscheme $color");
369 function! color#random()
370 let l:colorlist = globpath(&rtp, "colors/*.vim")
372 *my ($result, $colors) = VIM::Eval(
"l:colorlist");
373 return if $result !=
1;
374 my @available_colors = split(/\n/, $colors);
375 my %bad_colors = eval {
376 open(my $fh, '<',
"$ENV{HOME}/.vim/color_blacklist.txt");
377 map { chomp; ($_ =
> 1) } <$fh
>;
379 for (my $tries =
0; $tries <
100; ++$tries) {
380 my $colorpath = $available_colors[int(rand(@available_colors))];
381 my ($color) = $colorpath =~ m!([^/]+)\.vim!;
382 if (!$bad_colors{$color}) {
383 * VIM::DoCommand("colorscheme $color");
392 By the way, Vim supports embedded interpreters for other languages like Python, Ruby, and Lua in similar fashion.
395 class: center, middle
397 ## Document your shell scripts with pod.
408 therapist.sh - This script can save you a bunch of cash
412 echo 'Hello. Now, tell me about your problems.'
416 printf "Patient said: %s" "$response"
>>therapist_notes.txt
418 echo 'And how did that make you feel?'
421 echo "Goodbye! Let's meet again in two weeks."
433 *therapist.sh - This script can save you a bunch of cash
437 echo 'Hello. Now, tell me about your problems.'
441 printf "Patient said: %s" "$response"
>>therapist_notes.txt
443 echo 'And how did that make you feel?'
446 echo "Goodbye! Let's meet again in two weeks."
450 It's pod! In a shell script.
461 therapist.sh - This script can save you a bunch of cash
465 echo 'Hello. Now, tell me about your problems.'
469 printf "Patient said: %s" "$response"
>>therapist_notes.txt
471 echo 'And how did that make you feel?'
474 echo "Goodbye! Let's meet again in two weeks."
478 This is the key right here. Anybody know what this is?
482 The colon command in bourne shell is just noop. Sometimes you'll see the colon used as a type of comment, but unlike
483 a comment the shell does parse the arguments to colon.
486 class: center, middle
488 ## Understand calling context.
491 - One of the baffling things about Perl5 to newcomers is that subroutines can
492 do different things based on *where* they are used. This is called context.
495 ## The three main contexts:
501 ## The wantarray() function
502 - True if caller called in **list** context.
503 - False if **scalar** context.
504 - `undef` if **void** context.
507 Unfortunately this function was misnamed. It should have been "wantlist" since
508 there really is no "array context."
513 ## Example: localtime()
516 @time = localtime(); # -
> (
1,
43,
13,
7,
5,
118,
4,
157,
1)
517 $time = localtime(); # -
> "Thu Jun 7 13:43:01 2018"
523 ## Operators help determine context.
527 $thing_one . $thing_two
531 String concatenation is a scalar thing, so the concat operator
"creates" a scalar context on either side.
539 Numerical and comparison operators typically operator in the same way. So that's easy.
542 ### Scalar context on both sides.
547 ## Operators help determine context.
557 ### Also evaluated in scalar context.
560 - Generally the prefix and postfix operators also create scalar context.
563 class: center, middle
565 ## The assignment operator... is different.
568 What makes it different is that the assignment operator is really two different
574 ## The scalar assignment operator
577 $scalar = $another_scalar; # copy scalar on the right to the left
588 ## The scalar assignment operator
591 $scalar = $another_scalar; # copy scalar on the right to the left
595 $scalar = @array; # $scalar =
> length of @array
601 ## The scalar assignment operator
604 $scalar = $another_scalar; # copy scalar on the right to the left
608 $scalar = @array; # $scalar =
> length of @array
612 $scalar = qw(list of things);
618 ## The scalar assignment operator
621 $scalar = $another_scalar; # copy scalar on the right to the left
625 $scalar = @array; # $scalar =
> length of @array
629 $scalar = qw(list of things); # $scalar =
> "things"
633 ### Lists and arrays are **not** the same thing!
638 ## The list assignment operator
641 @array = @another_array; # copy array on the right to the left
652 ## The list assignment operator
655 @array = @another_array; # copy array on the right to the left
659 @array = $scalar; # $scalar copied; @array has one item
664 @array = qw(list of things); # contents of list copied to @array
670 ## Subroutines determine context of their parameters.
673 sub i_can_haz_scalar :prototype($) {
677 my @arr = qw(foo bar baz);
678 *i_can_haz_scalar(@arr);
682 Not only can subroutines branch and do different things based on the context
683 that calls them -- based on `wantarray()` -- they also control the context of
689 ## Subroutines determine context of their parameters.
692 sub i_can_haz_scalar :prototype($) {
696 my @arr = qw(foo bar baz);
697 *i_can_haz_scalar(@arr); # =
> 3
703 ## Subroutines determine context of their parameters.
706 sub i_can_haz_scalar :prototype($) {
710 *i_can_haz_scalar(qw{
2 4 6 8});
716 ## Subroutines determine context of their parameters.
719 sub i_can_haz_scalar :prototype($) {
723 *i_can_haz_scalar(qw{
2 4 6 8}); # =
> 8
727 Remember: Arrays and lists are no the same thing!
735 my %account_details = (
736 first_name =
> (split / /, $user_name)[
0],
737 job_title =
> fetch_job_title($user_name),
742 The reason it is important to understand contexts is because you will get
743 caught by gotchas if you don't.
745 Spot any potential problems here?
753 my %account_details = (
754 first_name =
> (split / /, $user_name)[
0],
755 * job_title =
> fetch_job_title($user_name),
760 sub fetch_job_title {
766 ### Can use the `scalar` function to force scalar context.
769 job_title =
> scalar fetch_job_title($user_name),
778 my %account_details = (
779 * first_name =
> (split / /, $user_name)[
0],
780 job_title =
> fetch_job_title($user_name),
784 ### `(split /regexp/, $str)[$index]` can evaluate to `()`!
787 This is surprising, right? Usually when you have a post-circumfix index
788 operator on either a list or an array, even if you go out of bounds you'll get
791 I should also mention that not only can things like this cause bugs that are
792 annoying and hard to find, there are security implications. If you're not aware
793 of how all the code within a hash declaration responds to being in list
794 context, you could potentially open the door for crafted user input to
795 overwrite completely unrelated keys in the hash.
798 class: center, middle
800 ## Understand execution phases.
809 That's easy enough. What's to know, right?
811 Well, it turns out that it's not so straightforward because unlike many other
812 languages, Perl can run code in the compile phase and compile code in the run
838 By the time this line executes we are already in the **run** phase.
840 So how do you actually run code in the compile phase?
845 ## Run code in compile phase
863 One way to run code in the compile phase is to create a `BEGIN` block.
868 ## Run code in compile phase
873 *use Data::Dumper qw(Dumper);
876 picard =
> 'jean-luc',
882 `use` statements are also fulfilled in the compile phase, so it doesn't matter
883 where they appear within the code.
885 Similarly, `no` statements are also performed at compile time.
890 require Data::Dumper;
891 Data::Dumper-
>import('Dumper');
896 A `use` statement is *almost* the equivalent of this here.
898 Also worth pointing out, the fact that code can be ran during the compile phase means that using the `-c` flag on an
899 untrusted script is not advised.
904 ## Compile code in run phase
910 my $calculate_answer = eval q[
912 return ] . ($hgttg ?
42 :
7) . q[;
916 print "The answer is ", $calculate_answer-
>(), ".\n";
920 String `eval` both compiles and runs strings as Perl code.
922 It gets a bad rap because of its security implications. Yes, generating code to compile and run on the fly, when based
923 on user input, must be done very carefully or not at all.
925 This technique is used by many Perl modules to "inline" optimized versions of their subroutines. For example, `Moo` and
926 `Moose` can generate constructors tailored for each class rather than always using one big constructor that can is able
927 to handle all the possibilities.
930 ## Code blocks associated with execution phases
932 - `BEGIN` - Runs the block immediately after it is compiled.
935 - `CHECK` - Runs the block after the main compile phase and before the main run phase.
938 - `CHECKUNIT` - Same, but for each "unit" (file).
941 - `INIT` - Runs the block immediately before the main run phase.
944 - `END` - Runs the block at program end.
946 Source: [Know the phases of a Perl programβs execution](https://www.effectiveperlprogramming.com/
2011/
03/know-the-phases-of-a-perl-programs-execution/) by brian d foy
949 By the way, it runs the blocks in a defined order, which is nice: `BEGIN` and `INIT` run in top to bottom order, while
950 the others run in the opposite order.
953 class: center, middle
955 ## Know when to be terse and when not to.
958 class: ex-obfuscated, center, middle
961 @P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{
962 @p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=
2)+=$f=!fork;map{$P=$P[$f^ord
963 ($p{$_})&
6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&
964 close$_}%p;wait until$?;map{/^r/&&<$_
>}%p;$_=$d[$q];sleep rand(
2)if/\S/;print
967 Source: [Just Another Perl / Unix Hacker](http://perl.plover.com/obfuscated/) by Mark Jason Dominus
970 This is what terse code looks like. At least I think it is... If I knew what it was doing, I would probably conclude
971 that it is in fact terse.
973 But actually, it might not be. For all I know this could be a very roundabout and verbose way to accomplish the work
974 it's doing. I can't tell because it's too "obfuscated."
977 class: center, middle
979 # obfuscation β terseness
982 The concepts of obfuscation and terseness are not materially equivalent.
984 Obfuscation is always bad (except in "toy" code like "Just another hacker" snippets and obfuscation challenges).
985 Terseness can be bad (if it's too obfuscated for the audience), but sometimes it can be better.
990 ## Be terse without obfuscating
995 @coordinates = @geodata[
2,
3];
996 @coordinates = ($geodata[
2], $geodata[
3]);
997 $coordinates[
0] = $geodata[
2]; $coordinates[
1] = $geodata[
3];
1001 Some language features are so common, they are idiomatic among users of the language even if the code may be somewhat
1002 perplexing to newcomers.
1004 Here are three more-or-less equivalent ways to do the same thing. The first way, using and array slice, is
1005 definitionally the tersest. Is it too terse? Is it obfuscated?
1007 In my subjective opinion, all three of these statements are equally fine. Array slicing is a language feature of Perl
1008 that doesn't exist in every other language, so it might perplex newcomers for a bit, but I think the intent is pretty
1009 clear even for those new to the syntax.
1011 So this is a great place to be terse.
1014 - Terse code can actually be faster for humans to parse.
1017 If only because there's less to read.
1020 - Talk to your peers (or downstream "users") and establish expectations.
1023 Some language features and style may just be too perplexing, so pay attention to who will probably be working with your
1026 You don't always have to code for the lowest possible common denominator.
1028 Example: A lot of code could be written in the functional style versus imperatively. Keep in mind that functional code
1029 is easier to read and write for math-minded programmers. Perl can do either, but which one you choose should depend more
1030 on who else is going to be working in your code rather than your own personal preference.
1033 - But **never** ever sacrifice clarity of intent for shorter code.
1036 Anyway, I don't have any solid wisdom for you on this topic. Just be mindful.
1039 class: center, middle
1041 ## Use [`Future::AsyncAwait`](https://metacpan.org/pod/Future::AsyncAwait).
1044 If you have used JavaScript recently, you may have used its "async/await" feature to clean up your non-blocking code.
1047 class: center, middle
1049 ### Yes, Perl can do it, too!
1052 class: ex-asyncawait
1054 ## Without async and await
1060 return do_first_thing()-
>then(sub {
1063 return do_second_thing($first)-
>then(sub {
1066 return Future-
>done([$first, $second]);
1073 class: ex-asyncawait
1075 ## With async and await
1078 use Future::AsyncAwait;
1080 async sub do_two_things
1082 my $first = await do_first_thing();
1084 my $second = await do_second_thing($first);
1086 return [$first, $second];
1091 There are caveats: Localized variable assignments don't work, nor anything that has implied local-like behavior.
1094 class: center, middle
1096 ## Write your own boilerplate.
1099 class: ex-boilerplate
1101 ### The boilerplate can get unwieldy...
1104 package My::Package;
1107 use warnings FATAL =
> 'all';
1109 use feature ':
5.14';
1110 use open qw(:encoding(UTF-
8) :std);
1111 use charnames qw(:full :short);
1113 use Encoding qw(decode encode);
1114 use Function::Parameters;
1115 use Locale::TextDomain 'AppName';
1116 use Scalar::Util qw(blessed refaddr reftype weaken unweaken isweak);
1117 use Unicode::Normalize qw(NFC NFC);
1123 class: center, middle
1125 ### Solution: Put all that junk in a separate package.
1128 class: ex-boilerplate2
1131 package My::boilerplate;
1139 my $target = caller;
1141 feature -
>import::into($target, qw{:
5.14});
1142 strict -
>import::into($target);
1143 warnings -
>import::into($target, qw{FATAL all});
1144 utf8 -
>import::into($target);
1145 open:: -
>import::into($target, qw{:encoding(UTF-
8) :std});
1146 charnames -
>import::into($target, qw{:full :short});
1148 Encode -
>import::into($target, qw{decode encode});
1149 Function::Parameters-
>import::into($target);
1150 Locale::TextDomain -
>import::into($target, $args{textdomain} || 'AppName');
1151 Scalar::Util -
>import::into($target, qw{blessed refaddr reftype weaken unweaken isweak});
1152 Unicode::Normalize -
>import::into($target, qw{NFD NFC});
1159 class: ex-boilerplate2
1162 package My::boilerplate;
1170 my $target = caller;
1172 feature -
>import::into($target, qw{:
5.14});
1173 strict -
>import::into($target);
1174 warnings -
>import::into($target, qw{FATAL all});
1175 utf8 -
>import::into($target);
1176 open:: -
>import::into($target, qw{:encoding(UTF-
8) :std});
1177 charnames -
>import::into($target, qw{:full :short});
1179 Encode -
>import::into($target, qw{decode encode});
1180 Function::Parameters-
>import::into($target);
1181 Locale::TextDomain -
>import::into($target, $args{textdomain} || 'AppName');
1182 Scalar::Util -
>import::into($target, qw{blessed refaddr reftype weaken unweaken isweak});
1183 Unicode::Normalize -
>import::into($target, qw{NFD NFC});
1190 class: ex-boilerplate
1192 ### Use your boilerplate.
1195 package My::Package;
1197 use My::boilerplate;
1207 Now I can use `say` without having to use perl
5.10 in my package, and I can use gettext to translate my greeting.
1208 Warnings and strict are also enabled. All that stuff I need in every module is there.
1211 class: ex-boilerplate
1213 ## Tip: Add this to your project's `.perlcriticrc`.
1216 [TestingAndDebugging::RequireUseStrict]
1217 equivalent_modules = My::boilerplate
1221 class: center, middle
1223 ## Write your own debugger.
1226 Perl provides rather convenient mechanisms for hooking into the interpreter.
1228 The idea for this topic, by the way, is from a lightning talk by rjbs in YAPC
2014. His talks are always entertaining,
1232 class: ex-owndebugger1
1235 perl -d:MyFancyDebugger program.pl
1239 This does at least two important things.
1242 ### `use Devel::MyFancyDebugger;`
1246 `$^P` is a bitfield that lets you turn on and off various features related to debugging. The value
1855 isn't important;
1247 just know that using this flag turns on a lot of those bits.
1250 class: ex-owndebugger2
1253 package Devel::PackageOrder;
1260 my ($package, $filename, $line) = caller;
1261 return if $seen{$package}++;
1262 print STDERR "Package: $package\n";
1270 perl -d:PackageOrder program.pl
1274 As it happens, the second bit of `$^P` arranges for a subroutine named `DB::DB` to be called per statement.
1277 class: ex-owndebugger2
1280 package Devel::PackageOrder;
1287 my ($package, $filename, $line) = caller;
1288 return if $seen{$package}++;
1289 print STDERR "Package: $package\n";
1297 perl -d:PackageOrder program.pl
1301 So, for each statement that gets run in your program, this subroutine is called. My simple example here just does some
1302 simple things. It uses the `caller` function to figure out where the program is at in its execution.
1304 The first item we get off of `caller` is the package name (actually we could also just call `caller` in scalar context
1305 to get just the package). Then, if we've seen the package before, we don't do anything, otherwise we print the name of
1308 So, this effectively tells us in what order packages
1310 Is this useful? I don't know. I guess it useful at some point because I wrote it. The point is, you can write your own
1311 debuggers to do whatever useful thing you have need of, when you have the need.
1313 And by the way, I've shown you the entirety of the debugger. There is no other code needed. It's really cool.
1316 class: center, middle
1318 ## Don't write your own debugger.
1321 As you can imagine, there are a lot of awesome debuggers on CPAN already.
1323 You should probably check before writing your own.
1326 class: ex-develtrace
1328 ## [`Devel::Trace`](https://metacpan.org/pod/Devel::Trace)
1331 perl -d:Trace -e'print scalar localtime, "\n"'
1332 *
>> -e:
1: print scalar localtime, "\n"
1333 Thu Jun
7 20:
43:
57 2018
1337 class: ex-develtrace
1339 ## [`Devel::Trace::Syscall`](https://metacpan.org/pod/Devel::Trace::Syscall)
1342 perl -d:Trace::Syscall=open -e'print scalar localtime, "\n"'
1343 Thu Jun
7 20:
45:
59 2018
1344 *open("/etc/localtime",
0x80000,
0666) =
3 at -e line
1.
1348 class: ex-develtrace
1350 ## [`Devel::NYTProf`](https://metacpan.org/pod/Devel::NYTProf)
1353 perl -d:NYTProf -e'print scalar localtime, "\n"'
1354 Thu Jun
7 20:
53:
42 2018
1357 ![NYTProf html report](img/nytprof.png)
1360 class: ex-develtrace
1362 ## [`Devel::Cover`](https://metacpan.org/pod/Devel::Cover)
1369 ![Cover html report](img/cover.png)
1373 class: center, middle
1375 ## Know the default perl5 debugger.
1378 Of course those other debuggers are cool, but don't forget that perl also comes with its own general-purpose debugger.
1388 Enter h or 'h h' for help, or 'man perldebug' for more help.
1393 #### That's about it...
1396 Obviously you can use it to step through code.
1398 Anyway, I don't have much to say about it. Just use it.
1401 class: center, middle
1403 ## Write modern Perl.
1406 class: ex-newfeatures
1408 ## Try some newer perl5 features.
1412 use feature qw(signatures); # available in v5.20
1413 no warnings qw(experimental::signatures);
1415 my $missile_inventory = {
1421 sub get_default_silo_id () {
1422 return $_ if
0 < $missile_inventory-
>{$_} for (sort keys $missile_inventory-
>%*);
1423 die "No more missiles. :-(\n";
1426 sub launch_missile ( $silo_id = get_default_silo_id() ) {
1427 die "Silo is empty.\n" if $missile_inventory-
>{$silo_id} <=
0;
1428 $missile_inventory-
>{$silo_id} -=
1;
1429 say "Missile launched from silo $silo_id.";
1434 class: ex-newfeatures
1436 ### Postfix dereferencing
1453 my @others = $person-
>{associates}-
>@*;
1454 my %associate_attributes = $person-
>{associates}-
>@[
0]-
>%*;
1457 ### `@{...}` can be `-
>@*` at the end
1458 ### `%{...}` can be `-
>%*` at the end
1461 class: ex-newfeatures2
1463 ### Subroutine signatures
1467 use feature qw(signatures);
1468 no warnings qw(experimental::signatures);
1470 sub only_one_arg($foo) {
1473 sub other_args_allowed_and_ignored($foo, @) {
1476 sub positional_and_named($args, %other) {
1483 class: ex-newfeatures2
1485 ### Strip leading space in heredocs
1492 Hi. The text here is indented in the source code,
1493 but not in the console!
1501 ## Use [`Moo`](https://metacpan.org/pod/Moo) and [`Moose`](https://metacpan.org/pod/Moose).
1506 use Function::Parameters;
1508 use namespace::clean;
1514 method fight($opponent) {
1515 $self-
>spear-
>thrust_at($opponent);
1522 - Gives perl5 an improved object model.
1523 - It partially is just syntactic sugar, right? But these modules do provide a lot of value about perl5's own object
1525 - Attributes and a constructor.
1526 - Roles (a.k.a. mixins).
1527 - And if you use Moose, you get the whole metaobject as well.
1528 - The metaobject provides introspection and runtime altering of classes. It's powerful.
1530 I'm not going to go any further into Moo or Moose, but do learn them and use them with a caveat: I don't know how anyone
1531 else feels about this, but I kinda like modules on CPAN that don't depend on Moo or especially Moose, because modules
1532 with fewer dependencies are just easier to work with generally. So, if you are releasing on CPAN, consider not depending
1533 on this. Or at least use Moo and not full Moose if you don't actually need the metaobject. Of course, in your own
1534 non-distributed programs, go all out.
1537 class: center, middle
1541 ![Camelia](img/camelia.png)
1544 - It's easy to install and fun to play with.
1547 class: center, middle
1549 ## Go download it and just start playing around.
1551 ### https://perl6.org/downloads/
1570 [*]
1,
2,
3,
4,
5 # -
> 120
1574 - This one is called the **reduce** meta operator.
1575 - Also notice that in Perl
6, you don't need to surround a list in parentheses.
1579 sub some-reducer($a, $b) { $a + $b }
1581 [[&some-reducer]]
1 ..
5 # -
> 15
1586 - Can reduce using any binary operator.
1587 - Oh yeah, and you can use dashes in subroutine names.
1600 You've seen the dot dot operator, but check out dot dot dot!
1608 1,
3 ...
9 # -
> 1,
3,
5,
7,
9
1609 2,
4,
8 ...
256 # -
> 2,
4,
8,
16,
32,
64,
128,
256
1614 my @fib =
1,
1, -
> $a, $b { $a + $b } ... *;
1617 @fib[
3 ..
5] # -
> 3,
5,
8
1618 @fib[^
8] # -
> 1,
1,
2,
3,
5,
8,
13,
21
1622 - Of course you can do even awesomer things like create infinite lists with more complicated sequence logic.
1623 - The list elements are evaluated lazily.
1628 ### Create your own operators
1631 sub postfix:<!
>(Int $n) { [*]
2 .. $n }
1637 Lots of languages (even perl5) allows you to override operators, but none come close to perl6 in functionality.
1641 Types of operators you can create in Perl
6:
1643 - Prefix (like `!` as in `!True`)
1644 - Postfix (like `++` in `$num++`)
1645 - Infix (like `+` in `
1 +
2`)
1646 - Circumfix (like `[]` in `[
1,
2]`)
1647 - Post-circumfix (like `[]` in `@array[
5]`)
1652 ### Destructure your structures
1655 sub salut(% (:name($name), :title($title))) {
1656 say
"Hello there, $name the $title!";
1659 salut({name =
> 'Bob', title =
> 'Consultant'});
1661 my %person = {name =
> 'Jean Luc', title =
> 'Captain'};
1666 I guess the first thing to say is that, yes, Perl
6 has function signatures.
1668 As this example shows, you can also do nifty stuff like destructure.
1672 ### Other cool stuff in Perl
6
1674 - Sigils that make [more] sense.
1677 - A real object model.
1680 - Types! -- If you want.
1683 - Multiple dispatch for subroutines.
1686 - Control over passing semantics.
1689 - Args are immutable by default, but can be set to copy or be mutable (like perl5 aliasing).
1699 - Use [`B::Deparse`](https://metacpan.org/pod/B::Deparse).
1700 - Know regular expressions.
1701 - Use [`Regexp::Debugger`](https://metacpan.org/pod/Regexp::Debugger).
1702 - Write Vim plugins in Perl.
1703 - Document your shell scripts with pod.
1704 - Understand calling context.
1705 - Understand execution phases.
1706 - Know when to be terse and when not to.
1710 - Use [`Future::AsyncAwait`](https://metacpan.org/pod/Future::AsyncAwait).
1711 - Write your own boilerplate.
1712 - Write your own debugger.
1713 - Don't write your own debugger.
1714 - Know the default perl debugger.
1715 - Write modern Perl.
1724 - Learn another language.
1725 - Learn software design patterns.
1728 class: center, middle
1736 class: center, middle
1742 Email me: Charles McGarvey
1743 <chazmcgarvey@brokenzipper.com
>
1746 Leave me feedback, if you want:
1748 ![Page on Joind.in](img/talkqr.svg)
1750 <https://joind.in/talk/
66955>
1758 - Thanks rjbs for your inspiring talks.
1759 - Thanks brian d foy for your instructive articles.
1760 - Thanks Damian Conway, Paul Evans, et al. for writing and sharing cool modules.
1761 - Thanks Larry Wall for Perl.
1765 </textarea><script src=
"https://gnab.github.io/remark/downloads/remark-latest.min.js"></script><script>var slideshow = remark.create({countIncrementalSlides: true, highlightLanguage: '', highlightLines: true, ratio: '
16:
9', /*slideNumberFormat: '',*/ navigation: {scroll: false, touch: false, click: false}})
</script><script src=
"js/common.js"></script><script src=
"js/slides.js"></script></body></html>
1766 <!-- vim: set ts=4 sts=4 sw=4 tw=120 et ft=markdown nowrap: -->