Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

It's the little things...

by Lady_Aleena (Curate)
on Mar 02, 2010 at 18:57 UTC ( #826230=perlmeditation: print w/replies, xml ) Need Help??

The other day I was told that I did not have to name a subroutine wanted just because the directions for File::Find used that name for it. I should have seen that from the get go, but I am one for following directions as written, in this case, sub wanted. Armed with this knowledge now, I can do more. I split up a module into two because I thought there was only on way to get the files found. I could go back and reintegrate them, but I decided to keep these modules, well, modular. :)

Then today, I was fiddling around with notepad++ and the colors for Perl, when I decided to see if the .pl file type was on the list. I clicked on it, then its edit button to see what was associated with it. To my chagrin I found that all this time I was typing perl could have just been typed

What was your moment where a little thing just popped up and bit you on the toe?

Have a nice day!
Lady Aleena

Replies are listed 'Best First'.
Re: It's the little things...
by liverpole (Monsignor) on Mar 02, 2010 at 19:35 UTC
        What was your moment where a little thing just popped up and bit you on the toe?

    Too many to even scratch the surface :), but one comes to mind...

    When I first started with Perl, I would get the base part of a filename with:

    my $iam = `basename $0`; chomp $iam;

    Which is silly, of course.  Why go to the shell when you've got Perl?

    For a long while I then used something I thought much more clever:

    (my $iam = $0) =~ s,.*/,,;
    Even as I type it now, my fingers still remember it from so much usage.  It worked great, but only in Linux.

    I finally started learning more about the available core modules, and now I know the way to go is:

    use File::Basename; my $iam = basename $0;

    As an aside to your meditation, if you're in Windows, you should be able to type just "filename" (without the .pl extension).  If it doesn't work, you may have to edit your "Advanced system settings" (under System in the Control Panel), and add ";.PL" to the end of the PATHEXT variable in your "System Variables" list.

      Which is silly, of course. Why go to the shell when you've got Perl?
      Perl is the ultimate glue language. You've got Perl. That means, using the shell is easy. It's designed to be easy to use different utilities. Not using the shell for the sake of not using the shell is very unPerlish.

      Now, in this particular case, I probably wouldn't use use the shell either, but there are many cases I don't hesitate to it.

            "Not using the shell for the sake of not using the shell is very unPerlish"

        <Sigh> -- Not exactly what I meant, but because you may have misunderstood my intended message, let me rephrase it:  Why go to the shell when you can do it just as easily in Perl?

        Of course I use the shell when it makes sense.  Without hesitation.  But it's not a good idea (for a number of reasons) to get in the habit of blindly running to the shell without considering the alternatives.  One reason the comes to mind is portability.  Another is speed.

        And yes, I'm aware that in a little program that uses the shell for nothing other than stripping the basename from its own path there is unlikely to be noticeably slower than its alternative.  But what if your script is so useful that some other program now calls it thousands or millions of times?  And some other program calls that one thousands or millions of times?  Eventually you run the risk of encountering leaky abstractions.

        I'll confess, there are plenty of times I've done:

        % cat somefile | grep somestring

        But I still try to be aware that it's overkill, just like instinctively using the shell (when you don't necessarily have to) can be.


      You can't prove it on me, because I never gave that code to anyone and deleted it ages ago, but when I started to write programs with perl, I had a bot that popened to netcat to perform a http request. I've no idea how that must have worked because obviously it has to feed data both to the input of netcat and read its output, so I assume it was something like $resp = `echo 'GET /$parms HTTP/1.1\nHost:\n' | nc 80`. (Note however that there was no many-argument pipe open at that time in perl 5.5005 or 5.6.) That it extracted data from the response html with bad regexen doesn't count as a big sin compared to the above I guess.

      As an aside to your meditation, if you're in Windows, you should be able to type just "filename" (without the .pl extension). If it doesn't work, you may have to edit your "Advanced system settings" (under System in the Control Panel), and add ";.PL" to the end of the PATHEXT variable in your "System Variables" list.

      Even though I am not too put out by having to type the filename with the extension, I took your advice but need to reboot. Thanks!

      Gives liverpole cookies!

      Have a nice day!
      Lady Aleena
Re: It's the little things...
by BrowserUk (Pope) on Mar 02, 2010 at 19:38 UTC
    I found that all this time I was typing perl could have just been typed

    Depending upon how your perl was install, you may find that you can just type filename to run your perl scripts.

    A way to check this (beyond just trying it), is to run the following command:

    c:\test>set pathext;.COM;.EXE;.BAT;.CMD;;.wlua;.lexe

    If .pl appears in the output (not necessarially at the beginning), then you probably can. To further check, try:

    c:\test>assoc .pl .pl=Perl

    And then:

    c:\test>ftype Perl Perl="C:\perl64\bin\perl.exe" "%1" %*

    And what all that tells you is that .pl is accepted as the extension for executable files. So, if you type filename, and there is a file called in your path, then .pl will be looked up in the associations, (to find "Perl"), and that will be looked up in the ftype database and the command template found there will be used to construct the command that will be executed.

    Hence, if I type filename, the command "c:\perl64\bin\perl.exe" "" will be executed.

    (I never understood why there is a two-stage lookup. There doesn't appear to be any way to have anything other than a one-to-one mapping. But that's how it is.)

    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.

      You can have several extensions associated to the same "type". Try "assoc .htm" and "assoc .html". Most likely they will be the same. And since you can actually set up several actions for a file type, it makes sense to allow this additional level of indirection.

      Enoch was right!
      Enjoy the last years of Rome.

Re: It's the little things...
by toolic (Bishop) on Mar 02, 2010 at 19:28 UTC
    Of the things I documented long ago, I think the discovery of Data::Dumper has been the most important.

      Data::Dumper is certainly one of the best perl module - the best friend to perl geeks.

      Data::Dumper and of course strict/warnings at the beginning of your code, those where the 3 main things that have helped me a lot with pretty much all perl code I have written since.

      Recently I have learned to love re 'debug' which can be a great help when trying to work out a complex occasionally "failing" regular expression.

Re: It's the little things...
by dHarry (Abbot) on Mar 03, 2010 at 11:04 UTC

    First Perl job, I was reusing (old) Perl code, and having zero Perl experience I just took the code for granted and made modifications to it. The author didn't use any modules and the code was quite lengthy. Later I found out about FTP and date handling modules. I was able to reduce the code by 80% or so and the code was also more robust (and no longer platform dependent!). This was a real eye-opener for me. Nowadays I start out by looking on CPAN instead of reinventing wheels:)

Re: It's the little things...
by webfiend (Vicar) on Mar 04, 2010 at 16:59 UTC

    That's a tough question for me, because part of the reason I love Perl is all the little things that are waiting to nibble my toes. It's a rich, delightful language, and I miss it every day when I clock in to work on some overbearing Rails project.

    I think the first playful nip from Perl was when I realized that I didn't need to explicitly specify scalar to get the length of a list - I could just assign the list to a scalar variable. I had already read this in the Camel book, but I stuck with scalar because I didn't trust Perl to do what I meant. I still remember the day the scales fell from my eyes, sitting in front of my Slackware machine with coffee in hand and suddenly seeing context in my Perl app where before I had seen only code.

    I continued using scalar in production code for a while, mainly because my coworkers and managers didn't really grok context.

    I've had many nibbles since, but that is the one sticks out in my memory.

      Curiously, for me, it was almost the opposite problem.

      I thought it was neat that I could just assign a list variable to a scalar variable and get its length.

      Or that I could use the list variable in list context and Perl would dutifully use the number ofelements in the list variable.

      And that's where I started to get into trouble...I often (too often!) THOUGHT I in scalar context where I was actually in list context! And that always seemd to bite me in really big, complicated scripts where I had to spend hours and hours tracing the source of the error!

      In the process, of course, I learned a LOT about contexts and when and where they apply.

      But what I also learned was that using scalar() ALWAYS preventd that problem.

      So, for me, the extra effort of typing the scalar() around the list variable has become second nature and saves me a lot of it makes my intentions clear and obvious to me and that those that have to maintain my code.

      But that's just what works for certainly is not elegant. YMMV.

      ack Albuquerque, NM

        I think what saves me is that I don't dig too deep into context - just enough to save myself a little effort. I've seen folks get into these bizarre mazes of context that completely lose me, but I avoid those in my own code.

Re: It's the little things...
by PeterPeiGuo (Hermit) on Mar 08, 2010 at 01:14 UTC

    There are so many little things with Perl and I guess we (myself and many others here) love perl, because of its great flexibility.

Re: It's the little things...when for/push is too much.
by Lady_Aleena (Curate) on Mar 06, 2011 at 10:07 UTC

    Its been a few days over a year since I first posted this node, but I have come across a few more little things that I am moved to gab about. Hopefully I am not reinventing the wheel.

    When for...push is too much

    Let's start off by with strict, warnings, and a normal hash with some data in it, shall we?

    use strict; use warnings; my %cbusers = ( 'BrowserUk' => 28, 'GrandFather' => 23, 'CountZero' => 20, 'wfsp' => 19, 'ambrus' => 19, 'Khen1950fx' => 18, 'atcroft' => 17, 'ELISHEVA' => 17, 'jwkrahn' => 16, 'Krambambuli' => 11, 'Lady_Aleena' => 9, 'Excalibor' => 7, 'Voronich' => 7, 'Eliya' => 7, 'gnosti' => 7, 'AndyZaft' => 6, 'frodonl' => 1, 'im2' => 1, );

    Now that we have our data (even though it says it is mine, I will share it with you) which is from the current users in the Chatterbox, let's play.

    for...push vs. map

    One way to create a list with data from another source blended into it is to loop it and push the new strings into another array. You can then print the array with join.

    my @cbusers_lines; for my $user (sort keys %cbusers) { push @cbusers_lines, "$user is a level $cbusers{$user} user"; } print join( "\n" , @cbusers_lines );

    Now that is all fine and well if you have another use for the list, however, if this is a once off deal, you might want to think about just using a map to get the job done. Though one shouldn't think of screen real estate, the following will help with that too.

    print join( "\n" , map( "$_ is a level $cbusers{$_} user" , sort keys +%cbusers ) );

    This was a great idea shown to me by someone else a long time ago for which I am still grateful. And see that there is less typing for you? :)

    for...push and List::Util::sum vs. +=

    Now we come upon a problem I had a few weeks ago. I was pushing a lot of numbers into an array, and I ran out of memory! (see A script with a loop is running my computer Out of memory) I was really scrambling after that. How was I to add lots and lots and lots and lots of numbers together that were being generated on the fly? Like the match against map above, how often are you going to use the array you are creating? More than once, you may want to push it; only once, well I will show you.

    my @cbusers_levels; for my $user (keys %cbusers) { push @cbusers_levels, $cbusers{$user}; } print sum(@cbusers_levels);

    In the above, you are storing the numbers in the array which is in memory. You are also calling in help from a module to add them all up. That might be okay for smaller lists, but even storing a list of all the levels of all the PerlMonks could slow down an older computer.

    A simple solution would be to keep adding to a variable and just store one number that keeps growing like so...

    my $cbusers_total_levels; for my $user (keys %cbusers) { $cbusers_total_levels += $cbusers{$user}; } print "Total: $cbusers_total_levels\n"; print "Average: ".$cbusers_total_levels / scalar(keys %cbusers); #even + get the average w/o importing

    Unlike the above (like it really matters), it doesn't save you real estate on the screen, but it could save your computer's memory from filling up.

    In closing whenever I find I am pushing an array, I ask "Is this the only time I am going to use this array?" If the answer is yes; I will more than likely go to a map if I am inserting text into a string for another source, or I will use += if I just want to add up a bunch of numbers.

    It is finding little things like this that makes Perl fun, and why I feel that Perl is a good game to play! (Well, not all the time, but most of it.)

    Have a cookie and a very nice day!
    Lady Aleena
Re: It's the little things...
by Lady_Aleena (Curate) on Apr 16, 2012 at 05:22 UTC

    Last Saturday I was rewriting a script and was getting sick of all of the ifs I was using. My code was to the point that I was 12 tabs down. Someone once said that about 4 was the maximum, so 12 was a bit much. Since I was in a for loop, I decided to finally see if I could get the hang of using next. OMG! The depth of my code got shallow rather quickly. I went from a depth of 12 tabs to 7. I felt a bit of joy at that point. I just wanted it share with you all how happy that little insight finally saved me from plunging too deep and having fewer brackets made it easier to find where I am when writing my script. Now I'm wondering how much unnecessary depth I have elsewhere. I think I will go spelunking.

    Have a cookie and a very nice day!
    Lady Aleena

      Maybe you should consider moving some of the code into separate subroutines. If you are 7 tabs deep, your code is most likely also rather long. Extracting and naming bits of it might make things more maintainable.

      Enoch was right!
      Enjoy the last years of Rome.

      Here's the next secret. You can get rid of just about all your nesting depth by replacing control structures (subroutines, for loops, etc.) with gotos. It's what you might call a higher level of wizardry, but it sounds like your nearly ready for it.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://826230]
Approved by Old_Gray_Bear
Front-paged by Arunbear
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2020-07-10 22:58 GMT
Find Nodes?
    Voting Booth?

    No recent polls found