Perl Hash Perplexity



  • In the Perl source code of a well-known network management software, I found a snippet very much like

    sub get_thingything
    {
        my $self = shift;
        my $k = shift;
        if($self->{thingything_hash})
        {
            my $thingything_hash = $self->{thingything_hash};
            for my $key(keys %{$thingything_hash})
            {
                if($k =~ /^$key$/i)
                {
                    return $thingything_hash->{$key};
                }
            }
        }
        return undef;
    }
    

    This hash is directly used ONLY by methods of this class.

    Apparently, they decided that Hash::Case was NYI, and using lc($key) on every access was inefficient, and implemented it on their own inefficient way.

    Exercise: what does this function do after the following code:

    $obj->{thingything_hash}->{".*"} = "TDWTF";
    


  • I never really did PERL. Because it's unreadable.

    And it just confirms my theory that you don't need a translator to read ruby or java code (I'm talking about code written by the fundamental principles of programming)

    Trolls away !



  • @ltouroumov said:

    I never really did PERL. Because it's unreadable.

    And it just confirms my theory that you don't need a translator to read ruby or java code (I'm talking about code written by the fundamental principles of programming)

    Trolls away !

    Indeed they are.


  • Really, though, if you want to bash Perl, "unreadable" is a weak and amateurish complaint. It's perfectly easy to write readable Perl. Now, this, on the other hand...

      DB<1> sub foo { +(0..20) } 
      DB<2> @bar = foo(); # list of 1, 2, 3, 4...20
      DB<3> x scalar @bar
    0  20
      DB<4> x scalar foo();
    0  ''
    

    That's right. When you call it directly like that, the scalar context propagates down into the subroutine call, turning the innocuous-looking .. into an entirely different operator (the "flip-flop" operator instead of the range operator). That, my friend, is ridiculous.



  •  Actually, the worst misfeature I've found in perl so far, was that `next` ignores function frames... Yeah... If you're confused:

    sub something {
       next if blah;
       ...
    }

    for my $a (@arr) {
       something();
    }

    The `next` inside `something` will actually skip to the next value in the loop outside of that function. Pretty, isn't it?



  • @viraptor said:

     Actually, the worst misfeature I've found in perl so far, was that next ignores function frames... Yeah... If you're confused:

    sub something {
       next if blah;
       ...
    }

    for my $a (@arr) {
       something();
    }

    The next inside something will actually skip to the next value in the loop outside of that function. Pretty, isn't it?


    That'll issue a warning, mind you. Assuming you use warnings; that is.



  • Perl Hash Perplexity, eh?

    Hmmm … you, sir, are a fan of the 1990s UK TV game show Banzai!. So I'll BET NOW! on that choice. :)



  • @fennec said:

    @viraptor said:

     Actually, the worst misfeature I've found in perl so far, was that `next` ignores function frames... Yeah... If you're confused:

    sub something {
       next if blah;
       ...
    }

    for my $a (@arr) {
       something();
    }

    The `next` inside `something` will actually skip to the next value in the loop outside of that function. Pretty, isn't it?

    That'll issue a warning, mind you. Assuming you use warnings; that is.

    It's been a thousand computer years since I last touched Perl, but am I correct in remembering that warnings are disabled by default? If so, that's TRWTF.



  • @fennec said:

    That'll issue a warning, mind you. Assuming you use warnings; that is.

    Perl is efficient. Not only can you solve any problem in less than five lines, but you can also determine if the author is an idiot by reading that many lines.

     

    @OperatorBastardusInfernalis said:

    Exercise: what does this function do after the following code:
    $obj->{thingything_hash}->{".*"} = "TDWTF";

    It returns "TDWTF" no matter what $k is.



  • @OperatorBastardusInfernalis said:

    Exercise: what does this function do after the following code:

    $obj->{thingything_hash}->{".*"} = "TDWTF";

    It does more than it would after

    $obj->{thingything_hash}->{")"} = "TDWTF";

    I don't imagine set_thingythinghash sanitises its input (or else why wouldn't it change the case at the same time?), but I hope that it does reject metacharacters, thereby shielding users from the brokenness of this function. Or, better still, that the function is never actually called.



  • @pkmnfrk said:

    It's been a thousand computer years since I last touched Perl, but am I correct in remembering that warnings are disabled by default? If so, that's TRWTF.

    Real men don't need no steenking warnings. If you can't stand the Perl, stay out of the kitchen. Ask not what Perl can do for you, but what you can do with a regex. The Perl stops here.



  • The fun part is that your answer is not 100% right. It depends on the semi-random order of the hash items...

    And no, the setter function for this does not sanitize any input or reject metacharacters.

    Luckily, the input doesn't come from the user of the software, or from a server... but is just internal.



  •  @ltouroumov said:

    I never really did PERL. Because it's unreadable.

    Don't you mean

    !$i->did('PERL') && it{'s'} eq 'unreadable';



  • @ltouroumov said:

    I never really did PERL. Because it's unreadable.


    Yeah, I never really did understand Russian or Greek. They're just so darn unreadable! And don't get me started on Chinese or Japanese!

    But seriously, that excuse is lame. It's perfectly readable to someone who has studied it.



  • @realmerlyn said:

    It's perfectly readable to someone who has studied it.
    ...as long as "study" means "read through perlintro and played with it for a few afternoons", then I completely agree.



  • @OperatorBastardusInfernalis said:

    The fun part is that your answer is not 100% right. It depends on the semi-random order of the hash items...

    You inserted other elements behind my back? You asshole! I can't believe I trusted you.

    Anyway, you should have seen the original answer I came up with before the ninja edit. Somehow I had managed to confuse $key and $k.



  • Here's how you'd write that function in Perl 5.10 by the way:

    sub get_thingything
    {
    	my ($self, $key) = @_;
    	my $thingything_hash = $self->{thingything_hash};
    	return $thingything_hash->{$1} if $thingything_hash ~~ /^($key)$/i;
    	return undef;
    }

     



  • @Faxmachinen said:

    You inserted other elements behind my back?
     

    Hey, what you do on the weekends is your own business.



  • @ender said:

    @realmerlyn said:
    It's perfectly readable to someone who has studied it.
    ...as long as "study" means "read through perlintro and played with it for a few afternoons", then I completely agree.
     

    Are you sure, you'd remember all the magic $X variables, crazy scoping rules, grouping vs lists, quoting vs interpolation rules, 10 randomly created pseudo-OO-lib conventions, etc. in a couple of afternoons? Yeah... I believe you. I have to deal with perl every day and it still continues to surprise me.

    Even if you do, some library can suddenly return you a dualvar which is an integer and a string at the same time and screws all your current plans. Damn it, if perl doesn't know if something is a number, only if it Scalar::Util.looks_like_number, how should anyone else know? use bytes. no bytes. use bytes. FUUUUUUUUUUUUUUUUUUUUCK

    Perl drives people insane!



  • If you want strong typing, Perl will not be your thing. That doesn't mean it's bad though.

     



  • @viraptor said:

    Are you sure, you'd remember all the magic $X variables, crazy scoping rules, grouping vs lists, quoting vs interpolation rules, 10 randomly created pseudo-OO-lib conventions, etc. in a couple of afternoons? Yeah... I believe you. I have to deal with perl every day and it still continues to surprise me.
     

    [url=http://perldoc.perl.org/perlvar.html]Magic $X variables[/url].  Just look them up when necessary.  Or [url=http://perldoc.perl.org/English.html]use English;[/url]

    The scoping rules are totally sane, or at least I've never come across any crazy ones.

    Do you mean lists verses list references..?  () vs []] ?   One is a list, the other is a scalar reference to a(n immutable) list.  Not a difficult concept for programmers.

    Single quotes don't interpolate, double quotes do.  Not that hard to remember.  You can also use q() and qq() for single and double if you want to use the quote characters in the string without lots of escapes. E.g., qq($name said, "$quote");  or  qq(<thingy attribute="hurr">$thingy_value</thingy>);

    Not sure what the random psuedo-OO-lib conventions mean.  Perl's OO isn't that strong, but is it really $that->hard()?  (#returns "no")

    $i->love("perl"); print q(I say, "It gets the job done.");

    $_=q(print"\$_=q($_);eval");eval



  • @viraptor said:

    Are you sure, you'd remember all the magic $X variables, crazy scoping rules, grouping vs lists, quoting vs interpolation rules, 10 randomly created pseudo-OO-lib conventions, etc. in a couple of afternoons?

    For my first programming internship, I was going to be using Perl (despite the fact that I had never used it before). I picked up the camel book, went through it in about a week, and had little problem with it during my internship. Was I a Perl guru (/monk) after that? No. Did I memorize all the $ variables? Hell no. But I don't memorize everything about any language I use. When I was using PHP, I had to look up things like argument ordering for builtin functions. I'm using C# now, and I often have to look at MSDN docs for class summaries. I don't think anyone can memorize everything about a language, not do I think they should.



  • @Xyro said:

    () vs [] ?   One is a list, the other is a scalar reference to a(n immutable) list.

    Surely you mean mutable?



  • @Xyro said:

    Magic $X variables.  Just look them up when necessary.  Or use English;

    Use english doesn't help when you're maintaining someone else's code.

    @Xyro said:

    The scoping rules are totally sane, or at least I've never come across any crazy ones.

    Standard example (not surprising if it's your code, pretty surprising if it happens in a function you don't control):

    sub bad_stuff { while(<>) {something_else;} }
    $_ = 20;
    print "now it's $_\n"; # 20 here
    bad_stuff;
    print "now it's $_\n"; # not available here
    Also - `use` imports into global scope - actually... kind of does. Makes it fun to change modules into strict.

    @Xyro said:

    Do you mean lists verses list references..?  () vs [] ?   One is a list, the other is a scalar reference to a(n immutable) list.  Not a difficult concept for programmers.

    Ah - concept is trivial - I agree. Debugging any application with this kind of introspection is hell (re.pl / Dumper's outputs):

    $ (1,2,3,4)
    $ARRAY1 = [ 1, 2, 3, 4 ];

    $ [1,2,3,4]
    $ARRAY1 = [ 1, 2, 3, 4 ];

    $ my %a = (1=>2, 3=>4)
    $ARRAY1 = [ 1, 2, 3, 4 ];

    $ (1,2,3,4) eq (1=>2, 3=>4)
    1

    $ (1,2,3,4) == (1=>2, 3=>4)
    1

    $ \[1,2,3,4]
    $REF1 = \[ 1, 2, 3, 4 ];

    $ \(1,2,3,4)
    $ARRAY1 = [ \do { my $v = 1 }, \do { my $v = 2 }, \do { my $v = 3 }, \do { my $v = 4 } ];

    I don't care that some of this stuff is "correct" in some bizarre way. Thanks to this, debugging perl is harder than it should be.

    @Xyro said:

    Single quotes don't interpolate, double quotes do.  Not that hard to remember.  You can also use q() and qq()

    Yes, ' " q qq qx qw m qr s and all the options that can take after the string. Ah, but then you can use a delimiter you want, qw/, qw{, ... Not that hard to remember.

    @Xyro said:

    Not sure what the random psuedo-OO-lib conventions mean.  Perl's OO isn't that strong, but is it really $that->hard()?  (#returns "no")

    Yes, but is it Moose, or Mouse? Or home-made? Are they type-checking-compatible? Can I assign to $that->{hard} to change the value (you can in some modules). Will $that->{hard} = ... call some function?

    @Xyro said:

    $_=q(print"\$_=q($_);eval");eval


    Yeah - and now I have to support some shit that looks like this. Tbh - I got used to it. I never use lists - arrays / hashrefs only, always force exact number of parameters, use strict, warnings, etc., rant every month to regain sanity and hope that one day all original perl programmers will die and go to hell...

    It's not that I can't or don't want to learn this stuff. I know it and see how much easier my life would be, if someone used a "sane language"™ instead



  • @viraptor said:

    I never use lists - arrays / hashrefs only, always force exact number of parameters
     

    So basicaly what you're trying to do is use Perl as if it was Java. Which is cool, only then I understand you hate it.



  • @b-redeker said:

    @viraptor said:

    I never use lists - arrays / hashrefs only, always force exact number of parameters
     

    So basicaly what you're trying to do is use Perl as if it was Java. Which is cool, only then I understand you hate it.

    Perl's like C++. The only way to use it sanely is to reduce the features you use to a sane level.

    I do enjoy your sentiment here, though. "Oh so you use it like a language that's roughly 20,000 times more popular than Perl!!! What a morons!!"



  • @viraptor said:

    sub bad_stuff { while(<>) {something_else;} }
    $_ = 20;
    print "now it's $\n"; # 20 here
    bad_stuff;
    print "now it's $
    \n"; # not available here

    Perhaps TRWTF is that you're using $_ as a standard variable, rather than a special variable and using it where it's meant to be used.



  • @blakeyrat said:

    I do enjoy your sentiment here, though. "Oh so you use it like a language that's roughly 20,000 times more popular than Perl!!! What a morons!!"
     

    Don't make me inappropriately extend your argument to php vs. everything else.

     

    I'm going to have a look at python soonishlike. I hear it's awesome, even though I still don't think formatting should affect execution to that degree.



  • @viraptor said:

    Debugging any application with this kind of introspection is hell (re.pl / Dumper's outputs):
    [snipped]

    I'm not sure what you're trying to say with that. Do you mean that if you know nothing about basic Perl syntax, it's hard to debug Perl programs? I mean, do you expect the result of numerically comparing two identical arrays to be anything but true?



  • @dhromed said:

    @blakeyrat said:

    I do enjoy your sentiment here, though. "Oh so you use it like a language that's roughly 20,000 times more popular than Perl!!! What a morons!!"
     

    Don't make me inappropriately extend your argument to php vs. everything else.

    Good point.

    @dhromed said:

    I'm going to have a look at python soonishlike. I hear it's awesome, even though I still don't think formatting should affect execution to that degree.

    Call me stupid, but I think it's a good thing that Python actually acknowledges that, hey, IDEs exist! And they can format code!! Let's use that. Instead of just assuming everybody's editing their code in edit.com circa 1985 like every other language does.



  • @dhromed said:

    Don't make me inappropriately extend your argument to php vs. everything else.
    Pfft. Only queers fail to see the awesomeness that is PHP.
    @dhromed said:
    I'm going to have a look at python soonishlike. I hear it's awesome
    Meh. If it threw less exceptions I'd be happy. Where the fuck am I supposed to sanely catch the CTRL+C exception?
    @dhromed said:
    I still don't think formatting should affect execution to that degree.
    What? If you have inconsistent indenting python will puke. If you don't it won't.



  • @blakeyrat said:

    "Oh so you use it like a language that's roughly 20,000 times more popular than Perl!!! What a morons!!"
     

    Eh... that's neither what I said nor is it relevant (as Dhromed pointed out). BTW, I would have said sth similar had he complained about how Java doesn't do stuff that it wasn't meant to do.

    I'm just saying that if you complain that your Ferrari can't carry a big load so you have to go to the store 4 times instead of 1, then maybe you're not usng it right. If you were using your mum's Volvo stationwagon to pick up chicks, same thing. Perl's data structures and parameter overloading have their uses - maybe not to pick up chicks but it can be damn useful.



  • @Faxmachinen said:

    @viraptor said:

    Debugging any application with this kind of introspection is hell (re.pl / Dumper's outputs):
    [snipped]

    I'm not sure what you're trying to say with that. ...

     

    That if I can't figure out a type of some value by printing it out, there is no hope for proper debugging of something. Sure there's "in context X" output... but that doesn't help me in any way, does it? I don't know any other language that would do this and it's certainly not an improvement (makes both writing and debugging harder) - so what else can I say - it looks broken to me. You're free to show me one use case where presenting a hash, list and array in the same way are an improvement over presenting them as what they actually are.

    @b-redeker said:

    So basicaly what you're trying to do is use Perl as if it was Java. Which is cool, only then I understand you hate it.

    I'd write Java differently. I'm trying to use perl in such way that it is easy to debug and maintain, which is a completely different thing. I don't see any value in using lists. Ever. Please show a case when it's more useful than an array if you think such case exists. Or in using variable number of parameters (you can always pass options in {key=>val} as the last parameter when "options" are needed)

    @toth said:

    Perhaps TRWTF is that you're using $_ as a standard variable, rather than a special variable and using it where it's meant to be used.

    I do not choose the code I work with. If it includes $_ I get crazy scoping rules. If it didn't include crazy scoping for special variables, I wouldn't complain - again - what's the usecase when this is an improvement? (no - `chomp` without arguments is silly, not an example here)

     @dhromed said:

    I'm going to have a look at python soonishlike. I hear it's awesome, even though I still don't think formatting should affect execution to that degree.

    The only people who actually have a problem with this are ones who don't indent code properly... If you keep it consistent (don't you always?) it's pretty much a nonissue. This is trivial to get used to.



  • @viraptor said:

     @dhromed said:

    I'm going to have a look at python soonishlike. I hear it's awesome, even though I still don't think formatting should affect execution to that degree.

    The only people who actually have a problem with this are ones who don't indent code properly... If you keep it consistent (don't you always?) it's pretty much a nonissue. This is trivial to get used to.

     

    That's not really a true statement. I indent pretty strictly.

    Sometimes you have to do some freeform formatting to make code more readable. In the case of Python, you'd be forced to find a workaround; a different syntax, and likely write more busywork code. However, I concede that this probably only happens with overblown code, such as 10 arguments for a function, or large if-conditions.

    I would have to start using it for real to see if it's a real problem or an imagined one.



  • @dhromed said:

    Sometimes you have to do some freeform formatting to make code more readable. In the case of Python, you'd be forced to find a workaround; a different syntax, and likely write more busywork code. However, I concede that this probably only happens with overblown code, such as 10 arguments for a function, or large if-conditions.

    I would have to start using it for real to see if it's a real problem or an imagined one.

    Python's parser actually handles those cases fine with minimal help.

    [robin@George1 ~]$ python test.py
    See?
    There.
    [robin@George1 ~]$ cat test.py 
    #!/usr/bin/env python
    def test(a,b,c,d,e):
    	print "There."
    
    if 10 > 4 and \
       50 > 33:
    	print "See?"
    
    test("asdfasdfasdf",
         "52342342",
         234234234,
         help,
         True);
    [robin@George1 ~]$ 
    

    Note: normal indentation is a tab here, then I have 3 spaces for the multi-line if, then 5 spaces for the multiple arguments on test().



  • @viraptor said:

    I do not choose the code I work with. If it includes $_ I get crazy scoping rules. If it didn't include crazy scoping for special variables, I wouldn't complain - again - what's the usecase when this is an improvement? (no - chomp without arguments is silly, not an example here)

    The scoping is only "crazy" because $_ is being used in a way it's not supposed to be used. Maybe you just don't like the idea of magic variables in principle, but it's really the developer's fault if they try to use a variable with certain documented behavior for certain documented purposes as a general-purpose variable.



  • @viraptor said:

    That if I can't figure out a type of some value by printing it out, there is no hope for proper debugging of something. Sure there's "in context X" output... but that doesn't help me in any way, does it?

    How does it not help you to know what the value is in context X, if X is the context in which it is used? And what's stopping you from writing your own REPL that prints the value in every possible context? Or is the problem that you actually want to figure out what the context is?



  • @blakeyrat said:

    [quote user="b-redeker"]

    [quote user="viraptor"] I never use lists - arrays / hashrefs only, always force exact number of parameters

     

    So basicaly what you're trying to do is use Perl as if it was Java. Which is cool, only then I understand you hate it.

    [/quote]

    Perl's like C++. The only way to use it sanely is to reduce the features you use to a sane level.

    I do enjoy your sentiment here, though. "Oh so you use it like a language that's roughly 20,000 times more readable / useful / sane than Perl!!! What a morons!!"[/quote]

    FTFY.

    Seriously, PHP is about the only scripting language I've used that doesn't make me want to stab myself in the dick when I write scripts with it. And at least when I come back to a PHP script a year later, I'll still understand what it's doing.



  • I wrote you a new REPL. You can thank me later.

    use strict;
    use warnings;
    no warnings qw(void);
    

    $" = ', ';
    print "$ ";
    while (<>)
    {
    chomp;
    while (/(@\w+)/g) { my @v = eval "$; $1"; print "$1 = ARRAY( @v )\n"; }
    while (/(%\w+)/g) { my %v = eval "$
    ; $1"; my @k = keys %v; my @v = values %v; print "$1 = HASH(( @k ) => ( @v ))\n"; }
    while (/(((?:[^()]+|(?1))*))/g) { my @v = eval "$1"; print "$1 = LIST( @v )\n"; }
    my @v = eval;
    if (scalar @v == 1) { print "$_ = SCALAR( $v[0] )\n"; }
    print "\n$ ";
    }

    See? Much better:

    $ (1,2,3,4)
    (1,2,3,4) = LIST( 1, 2, 3, 4 )
    

    $ [1,2,3,4]
    [1,2,3,4] = SCALAR( ARRAY(0x1843cc4) )

    $ my %a = (1=>2,3=>4)
    %a = HASH(( 1, 3 ) => ( 2, 4 ))
    (1=>2,3=>4) = LIST( 1, 2, 3, 4 )

    $ (1,2,3,4) eq (1=>2,3=>4)
    (1,2,3,4) = LIST( 1, 2, 3, 4 )
    (1=>2,3=>4) = LIST( 1, 2, 3, 4 )
    (1,2,3,4) eq (1=>2,3=>4) = SCALAR( 1 )

    $ (1,2,3,4) == (1=>2,3=>4)
    (1,2,3,4) = LIST( 1, 2, 3, 4 )
    (1=>2,3=>4) = LIST( 1, 2, 3, 4 )
    (1,2,3,4) == (1=>2,3=>4) = SCALAR( 1 )

    $ [1,2,3,4]
    [1,2,3,4] = SCALAR( REF(0x183e5a4) )

    $ (1,2,3,4)
    (1,2,3,4) = LIST( 1, 2, 3, 4 )

    Okay, so it's not perfect. You'll figure it out, though.


Log in to reply