Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm happy to say I just passed the Perl certification on Brainbench and as promised, my employer is raising my salary %15.

There are two questions I was unsure of and I was wondering if someone could explain them to me. I saved the few I was guessing on.

my $data = "Hello World" =~ /(.*) (.*)/; print "$data\n";
This one I got wrong as I expected it to print "Hello World". Instead it prints "1". Can someone explain this phenomonon to me? It's not s///, it's m//, right? So why is $data altered?

When does a BEGIN block execute?
I said it begins when the script encounters the BEGIN statement. It was either between this one or during compilation. Can anyone help me out with this one?

Thank you for your help.

20040708 Edit by ysth: Add readmore tags to keep spoilers off front-page

  • Comment on WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
  • Select or Download Code

Replies are listed 'Best First'.
Re: WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
by tachyon (Chancellor) on Jul 02, 2004 at 04:43 UTC

    a) Perl Idioms Explained - @ary = $str =~ m/(stuff)/g covers this but in essence you are assigning the return value of m// (yes /.../ == m/.../ ) to a scalar. What is the return value? See perlre but it is 1 (true) if there is a match and false (null string) if there is no match. $data *is not altered* - it was never set to 'Hello World' due to precedence ie the expression parses as $data = ( 'string' =~ m/stuff/ );

    b) BEGIN executes at the begining ie compile time before CHECK, INIT and of course END. These four block types run in this order:

    • BEGIN - Runs ASAP (as soon as parsed) whenever encountered during compilation, before compiling the rest of the file.
    • CHECK - Runs when compilation is complete, but before the program starts.
    • INIT - Runs at the beginning of execution right before the main flow of your program starts.
    • END - Runs at the end of execution right after the program finishes.

    Congrats on the payrise. Who says these sorts of tests are pointless!

    cheers

    tachyon

      That is one of the goofiest context-things I've ever seen. Must mean why if you want the number of matches, you need to do
      my $data = () = "Hello World" =~ /(.*) (.*)/;

      ------
      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I shouldn't have to say this, but any code, unless otherwise stated, is untested

        Perhaps it is because of the difficulty in defining matches? For example I would call this example one match that *returns* a two element array ( $1, $2 ). I might well expect it to return 1, you evidently expect 2. I do agree that it is non intuitive.

        cheers

        tachyon

Re: WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
by Juerd (Abbot) on Jul 02, 2004 at 08:38 UTC

    Unless Brainbench has changed a lot since June 17, 2000, don't be too proud. 15% more salary for having basic knowledge seems unfair if you have been coding Perl all along.

    I got certified in 2000 by Brainbench as a "Perl Programmer" at "Master" level. That was one year after first using Perl. I didn't even use strict back then. The Brainbench certification tests I did are the most meaningless tests I know. I have 14 of those certificates, including in subjects that I did really not know about (like, ehm, "Javascript Programmer". I only recently learned that Javascript has anonymous functions (and closures), that objects are arrays and what kind of scoping it has.).

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
by calin (Deacon) on Jul 02, 2004 at 14:45 UTC

    Context, my friend...

    $ perl my $data = "Hello World" =~ /(.*) (.*)/; print "$data\n"; ^D 1
    $ perl my ($data) = "Hello World" =~ /(.*) (.*)/; print "$data\n"; ^D Hello

    The first example is a scalar assignment ; $data is assigned the value of "Hello World" =~ /(.*) (.*)/ in scalar context, which is "true", by convention "1". The second example is a list assignment ; $data is assigned the string captured by the first capturing paren, that is, "Hello".

    See the documentation on m// in perldoc perlop.

    P.S. ++dragonchild for my $nmatches = () = $stuff =~ m/.../; Now one might ask: why m// doesn't return the number of matches in scalar context in the first place? I think the reason lies with the /g modifier which behaves differently in scalar and list contex. Also, for capturing parens, the "number of matches" is constant (it's really all or none), so the designers of the language decided to stay consistent and return "1" in all situations. Any more insight?

    Update: Fixed small error in code

Re: WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
by blueAdept (Beadle) on Jul 02, 2004 at 15:44 UTC
    If you wanted to preserve the integrity of the test you shouldn't have mentioned it at all.(after all questions of these sorts are commonplace here) Being that you did though it seems like you're giving them a shameless plug.
Re: WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
by Jasper (Chaplain) on Jul 02, 2004 at 16:27 UTC
    I wouldn't take the Brainbench test in the hope of getting a maximum raise of $14.

    Bam!
Re: WARNING!! Possible Brainbench spoilers (do NOT read unless you've taken and passed the cert)
by Anonymous Monk on Jul 02, 2004 at 18:57 UTC
    my $data = "Hello World" =~ /(.*) (.*)/;

    Is two statements in one. Look at it as:

    my $data = ("Hello World" =~ /(.*) (.*)/);

    or more clearly. Assign the output of

    "Hello World" =~ m/(.*) (.*)/);

    to

    my $data