What I Most Recently Learned in Perl, But Should Have Already Known
liverpole
created: 2006-08-16 18:43:31
When I began learning Perl, almost exactly 6 years ago, it was so much fun that I couldn't get enough of learning new things.  I had bought Learning Perl, vol. 2, a couple of years earlier, but hadn't made much of a dent in it, mostly because I wasn't involved in actually using it for any programming.  So just reading about it was doomed to failure, in retrospect.

But in the summer of 2000, I was using it for work, and loving the process.  The book "Learning Perl" (and several other newly-acquired Perl books as well) now became not only useful, but a source of new learning and fresh inspiration each time they were opened.  It even became a habit to read chapters from Perl books in my spare time, just to learn all the cool constructs I had never encountered in any other languages.  I still remember the excitement I felt discovering for the first time about tied variables.  Or grasping the beauty of data structures which behaved one way in scalar context, and another way in list context, and the sheer beauty and logic of such a system.  Or the intricate wealth of reusability that came from writing object-oriented modules.

And of course, the plethora of functions!  Every time I researched this still-new (to me) language, there were all the functions that I loved in C, and new ones everywhere I looked.  Add to that the complex user-defined data structures, sophisticated regular expressions, elaborate subroutine closures ... "Swiss-army Chainsaw" didn't even begin to describe the power!

But I have to admit I don't spend the same long hours reading about Perl the way I used to.  I'm sure it's a common phenomenon for many; you look up what you need, when you need it, and that's about all.  I did recently purchase Mark Jason Dominus' book, "Higher Order Perl", and although it's a fascinating and thoroughly illustrative book, I confess that I only read maybe 10-20 minutes of it at a time, not the 2-3 hours that I used to spend entrenching myself in learning.  One gets to a point, perhaps, where it one feels that they know essentially all of the basics; no more big surprises when it comes to the fundamentals.

So it was today that I surprisingly came across something simple that I realized I didn't know how to do.  While writing a program to demonstrate the application of the [wikipedia://Bailey-Borwein-Plouffe formula], I couldn't figure out how to to convert a very long string, containing a binary value, into a hexadecimal value.  I knew about [doc://hex] and [doc://oct], but there isn't a bin equivalent, and though [doc://sprintf] will output in binary, there wasn't an obvious way to make Perl treat my string as binary on input.  

When I came across the answer, I realized I had missed something basic, back when I was just starting out with Perl.  The [doc://oct] function can work with a variety of input bases (not just octal), by specifying the base at the front:

    0xN .... interpret N as hexadecimal
    0bN .... interpret N as binary
      N .... interpret N as octal

And the [doc://oct|oct documentation] even suggests a method of handling any of the common 4 bases, with:

    The following will handle decimal, binary, octal, and hex
    in the standard Perl or C notation:

        $val = oct($val) if $val =~ /^0/;

So now I'm wondering what other basics I may have missed along the way, either because I never noticed them the first time through, or just didn't need to know them until now.

And I'm curious, and ask the question of you, my brethren:  "What basic function, construct, or concept in Perl did you recently learn, that you were surprised to find you hadn't already known?"


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-16 18:55:23

You may want to look at pack and unpack too.


DWIM is Perl's answer to Gödel
Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-16 19:02:15
Yes, GrandFather, I know about pack and unpack.  And although I don't consider myself an expert at them (... yet :-D), I have used them in quite a few programs to date.  Anyone who has done socket programming (for example) will certainly have learned how to use them.

But how about you?  Do you have any stories to share about concepts which you've learned in the recent past?


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re^3: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-16 19:19:41

I learned something about pack/unpack writing [id://534371]. But the cool thing I learned writing that code was using can to assist in the context of a "dispatch by name":

        my $member = "dump_$key";
        my $name = "name_$key";
        
        $name = $self->can($name) ? $self->$name () . ' ' : '';
        ...
        if ($self->can($member)) {
            $self->$member ($pos, $len);

$key is an "atom" code from the file being parsed. If there is a handler for the atom $self->$member dispatches to the code to handle it. One neat thing about this is that a derived class can add handlers and the parser just takes it all in its stride. I reckon that's pretty cool - perhaps even elegant. :)

One way to do a binary conversion is:

my $str = '001100010011001100110001';
my $value = pack ('B*', $str);
print $value;

DWIM is Perl's answer to Gödel
Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 04:34:53
One thing that bit me a few months ago: sort in scalar context is undefined.

That isn't a big deal until you do this in a sub:

return( sort @some_array );

that is supposed to return a sorted list. And then you wonder how many elements the list contains:

my $count = get_the_sorted_list();  #Scalar context propagates to sort

That's pretty annoying when you happen to do it, and pretty important to know about so you don't. I sure was surprised the first time I encountered it.

/J

Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 06:57:45

I've discovered that an excellent way to dust off those less-than-oft remembered features of Perl is to try to interpret the obfuscated JAPH programs. You wind up looking up deprecated and seldom-used operators and functions in the course of trying to decipher what those things do.

The advantage to this is that it sometimes gets your creative juices flowing in a new way, and suddenly study might be your newest old toy.

Musing,
-v.

"Perl. There is no substitute."
Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 09:04:18
I cannot agree with this more. I learned most of the Perl I know today through Perl Golfing (both participating and decoding other answers).

Ted Young

($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)
Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-19 08:43:20
I am afraid to look into the aby... at obfuscated/golf code, since I am afraid it might look ba... be contagious.

(-: Are you saying that I should relax -- it helps keyboard speed if my fingers transform into tentacles and Cthulhu worshippers can scuba dive cheaper because of breathing under water? :-)

I recently learned how neat parsing parameters is with Getopt::Long.

What I've learnt the last year or so is to write tests for all code I write. The main advantages are development speed (for larger code), that you organize your code differently so it is testable and it really helps when you rewrite code.

For my hobby project, I'm going to make an alternative implementation of a feature (big data volumes will be stored in a sql database). I can copy the tests and keep the interface! Neat.

Since that was borderline elegant, I'll also show a monk's humility by mentioning a horrible kludge I'll add to that. Objects will rebless themselves to the other implementation type when the data size gets larger/smaller! (A nicer implementation would be to have an implementation of the storage which are contained in another object -- and let that create/delete objects with data. That gets complicated for other reasons.)

Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 07:03:47
Using a foreach loop on an AoH creates an alias of the hash which goes out of scope after the loop.

#!/usr/bin/perl 

use strict;
use warnings;

my $recs = [
  # short records for brevity
  {id => 1},
  {id => 2},
  {id => 3},
];

my $rec;

for $rec (@{$recs}){
  # $rec is an alias...
  if ($rec->{id} == 1){
    last;
  }
}

# ... which is now out of scope :-(
print "$rec->{id}\n"; # Use of uninitialized value...

# what I should have done
($rec) = grep {$_->{id} == 1} @{$recs};

print "$rec->{id}\n"; # 1

Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 18:55:17
# $rec is an alias...

It's the previously declared lexical, implicitly localized. See [http://perldoc.perl.org/perlsyn.html#Foreach-Loops-for-foreach|perldoc perlsyn]...

Shorter example, without the need to blame AoH for the problem:

my $var = 4;
for $var (1 .. 9) {
    last if $var == 7;
}
print $var;  # prints: 4
Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 12:29:04

unless, once I learned it, I quit having to create complex if-else statements to decide if something did not happen. All languages should have an equivalent to unless

Thank you,
Greg W
Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-17 13:28:53

Continuing the if-else statements problem, the idiom I like most is:

my $function = 'a';
my %functions = (
    'a' => sub { ... },
    'b' => sub { ... },
);
$functions{$function}->();

It's amazing how this replace an entire switch or if-else statements.

Igor 'izut' Sutton
your code, your rules.

Re^3: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-18 12:48:50
I always run into the problem of the default case when I use that -- what if $function isn't a key in %functions? The error message "Undefined subroutine &main:: called" can be very difficult to figure out.

And the straightforward fix isn't all that pretty:

($functions{$function} || $functions{default})->();
But I admit that I still use it. With comments, if there is any chance that someone with a capacity to do me bodily harm might read the code.
Re^4: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-18 16:43:23

I think this way is prettier.

sub do_something {
    my ($function) = @_;
    $function = 'default' unless exists $functions{$function};
    $functions{$function}->();
}

Igor 'izut' Sutton
your code, your rules.

Re: What I Most Recently Learned in Perl, But Should Have Already Known
imp
created: 2006-08-17 20:14:12
That you can get an array of hashes from DBI like this:
my $aoh = $dbh->selectall_arrayref($sql,{Slice => {}});
Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-18 18:57:43
well, few days ago I 'discovered' ||= operator ;)

greetz, Uksza

Yes, smart people know that fat arrow autoquotes the left argument. But why should you require your code to be maintained by smart people?
Randal L. Schwartz, Perl hacker
Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-20 22:09:13
Nice insight into your Perl experience!
Re: What I Most Recently Learned in Perl, But Should Have Already Known
imp
created: 2006-08-20 22:37:56
I recently learned how to find out what Perl thinks I mean by my code. The magic of [cpan://B::Deparse]. This answered some mysteries, for example why this code will not stop on values that are seen as false:
while (<>) {
}
When writing that loop explicitly I would be testing it like this:
while (defined( my $line = <>)) {
}
It turns out that is exactly what perl is doing as well, as seen below:
perl -MO=Deparse -e 'while (<>) {}'
while (defined($_ = )) {
    ();
}
It's also interesting to see what the parser thinks about other code, such as:
perl -MO=Deparse -e ' if(1) {print "true"}'     
do {
    print 'true'
};
And
perl -MO=Deparse -e ' print "true" if 1'   
print 'true';
And it is useful for seeing what some of the code from the Obfuscation section is actually doing.
Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-21 06:55:29
perl -MO=Deparse -e ' print "true" if 1'

If we do if 0 something even funnier happens:

$ /usr/bin/perl -MO=Deparse -e 'print "true" if 0'
'???';

But which is most amusing is the fact that the deparsed code generates a warning:

$ /usr/bin/perl -w -e 'print "true" if 0'
$ /usr/bin/perl -w -e '"???"'
Useless use of a constant in void context at -e line 1.

--
David Serrano

Re^3: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-23 05:36:05

'???' actually is no real thing. It's more like Deparse saying, this should be optimized away.

E. g. every "Useless use of a constant in void context" also results in this.

Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-21 07:25:51
Hi imp,

I myself didn't know about B::Deparse until about a half a year ago, and only then as a result of being pointed to it by the other monks.

If you haven't seen it yet, check out this obfuscation, which I wrote to take advantage of some of the properties of B::Deparse.


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-22 14:08:52
Map and grep. Especially for set functions, e.g. (untested code, but that should give the idea)
my @a=(1,2,3,4,5);
my @b=(4,5,6,7,8);

my %a = map { $_ => 1 } @a;
my %b = map { $_ => 1 } @b;

my @intersection = grep { exists $a{$_} } @b;
my @intersection_complement = grep { !exists $a{$_} } @b;
Re^2: What I Most Recently Learned in Perl, But Should Have Already Known
created: 2006-08-23 04:49:25

That reminds me that some time back I tried to get a grip on hash slices.

In similar use to your example:

my @intersection = grep {defined} @{{map {$_=>$_} @a}}{@b}

Though in everyday life I prefer your method, since I tend to get headache from thinking about that slices and also definitely got the syntax and/or semantics wrong the first time always.

Re: What I Most Recently Learned in Perl, But Should Have Already Known
imp
created: 2006-08-22 17:17:24
I was aware of this:
my $indent = ' 'x5;
# Yields '     '
But didn't realize I could also do this:
my @list = (1)x5;
# Yields (1,1,1,1,1)
So I can stop doing this:
  @placeholders = map {'?'} @columns;
And start doing this:
  @placeholders = ('?')x @columns;

perlmonks.org content © perlmonks.org and arpie, BerntB, gawatkins, GrandFather, Hue-Bond, imp, izut, jplindstrom, liverpole, pKai, Ray Smith, sfink, TedYoung, uksza, Velaki, wfsp

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03