Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

can understand one line of code

by anaconda_wly (Scribe)
on Dec 19, 2012 at 15:14 UTC ( #1009573=perlquestion: print w/ replies, xml ) Need Help??
anaconda_wly has asked for the wisdom of the Perl Monks concerning the following question:

Below is one line in Win32\TieRegistry.pm .I can't understand it.

grep( s#$#$RegObj->{DELIM}#, @{ $RegObj->{MEMBERS}= [ @{$RegObj->{SUBKEYS}} ] } );

what does it mean for grep function's 2 argument? what on earth "s#$#"mean? Thanks!

Comment on can understand one line of code
Download Code
Replies are listed 'Best First'.
Re: can understand one line of code
by BrowserUk (Pope) on Dec 19, 2012 at 15:24 UTC

    Break it down:

    1. grep( expression, @{ ... } )
    2. The expression  s#$#$RegObj->{DELIM}#

      start with 's', so it is a substitution.

      The #s are delimiters so the two sides are: $ and $RegObj->{DELIM}

      So it is substituting the module defined delimiter for any '$'s every end of line.

    3. The array: @{ $RegObj->{MEMBERS}= [ @{$RegObj->{SUBKEYS}} ] }

      Contains an assignment: $RegObj->{MEMBERS}= [ @{$RegObj->{SUBKEYS}} ]

      It copies the array of subkeys : @{ $RegObj->{SUBKEYS} } into an anonymous array [ ... ]

      And assigns its reference to $RegObj->{MEMBERS} = ...

      Then it dereferences that to supply the subkeys to grep.

    Thus, that one line is equivalent to:

    my @temp = @{ $RegObj->{SUBKEYS} }; $RegObj->{MEMBERS} = \@temp; grep s[$][$RegObj->{DELIM}], @temp;

    Without the need for @temp; but less efficient.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    RIP Neil Armstrong

Re: can understand one line of code
by toolic (Bishop) on Dec 19, 2012 at 15:23 UTC
Re: can understand one line of code
by tobyink (Abbot) on Dec 19, 2012 at 15:22 UTC

    It's quite obscurely written, but, it's roughly equivalent to:

    my @results; my @tmp_array = @{ $RegObj->{SUBKEYS} }; $RegObj->{MEMBERS} = \@tmp_array; for my $member (@{ $RegObj->{MEMBERS} }) { next unless $member =~ /\$/; $member =~ s/\$/$RegObj->{DELIM}/; push @results, $member; } @results;
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: can understand one line of code
by roboticus (Chancellor) on Dec 19, 2012 at 15:39 UTC

    anacondy_wly:

    The s#xxx#yyy# is just an alternate form of s/xxx/yyyx. With the s and </c>m</c> operators, you can specify an alternate set of delimiters for your regex. It's often used to make an expression easier to read--for example, if you're altering strings with slashes in them (think directory paths), then you'd need to prefix each '/' with a '\' inside your regular expression if you used the typical '/' delimiter. If you choose a different delimiter, though, it can be easier to read. Note: You can also used curly braces, too. These three expressions are identical:

    $t =~ s/\/home\/roboticus\/tmp/\/home\/postgresql\/tmp/; $t =~ s{/home/roboticus/tmp}{/home/postgresql/tmp}; $t =~ s#/home/roboticus/tmp#/home/postgresql/tmp#;

    So since the grep statement gets a list of aliases, the statement is first altering the value, then checking whether it should be included in the output list. A trivial example:

    $ cat t.pl #!/usr/bin/perl my @a = qw(apple banana cherry durian); my @b = grep { s#(a.)+#x#g; m/x/ } @a; print join(", ", @b), "\n"; $ perl t.pl xple, bxa, durix

    Finally, the statement doesn't look like it's syntactically correct, but as I understand it the grep command is doing another transformation: It seems to be setting the MEMBERS item to the number of an array ref of a list of the SUBKEYS. Then, since grep evaluates each element in scalar context, the grep statement keeps the item if and only if there are any SUBKEYS. However, $ isn't a variable, so the first bit of the code block looks incorrect. Secondly, since nothing changes $RegObj, I don't see what good is going to happen: it seems to me that either all elements would be retained in the list, or none of them would.

    If no objects are supposed to be retained, then I'd simply use a for loop to process the items. If all items should be retained, then I'd replace the statement with a map statement.

    Just my $0.02.

    Update: Jiminy, I'm slow. Three answers before I replied, and they show that I goofed. I also obviously got it a bit wrong. (That's what I get for not testing.) I was expecting a variable expansion in the match portion of the regex. (I don't know *why* I expected it, as '$' is the 'end of line' match character. Perhaps I was thrown off by the use of something that looked like a variable name on the right side.) So anyway, I've stricken the bit that's patently incorrect, and underlined a bit of text I inserted to partially correct it.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      OK. I understand. Thank all of you for the quick, precise and clear answer. I read everyone's answer carefully. All are very great! Thanks!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1009573]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (9)
As of 2015-07-29 22:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (269 votes), past polls