2mths has asked for the wisdom of the Perl Monks concerning the following question:

In short: How could and or should I simplify this?...
$var = `return from some system call`; chomp $var; print "$var";
The aim of the code is to strip the newline from the end of the item returned from system and then print the rest.

Wibble: Monks, I am frequently impressed by the code\solutions\discussions posted here. In my quest to improve myself and my Perl I would like to write better code but I seldom glean insight from the stuff posted as it's too far above my level. I hope I won't displease senior monks too much with this question. The answers I hope will bring the greatest improvment in my current understanding and codeing (as I hope any techniques demonstrated can be applied in other 'in line' simplificaitons).

Replies are listed 'Best First'.
Re: Simplifying code (Not obfuscation)
by zakb (Pilgrim) on Mar 04, 2003 at 10:32 UTC

    In Perl, there's more than one way to do it, and your way is almost perfectly fine (by me).

    First up, I would hope that you're using strict and warnings, and that $var is actually declared as my $var. This will help you in the future; see Why use strict/warnings for why.

    The other improvement I would suggest is to lose the double quotes in your print statement if all you're printing is $var, i.e.:

    print $var;

    is sufficient.

    One other thing you may want to do is check whether the system command actually executed successfully. The backquote returns undef if the command failed, and it would be good practice to check for this.

    There are undoubtedly other things you can do, but with these suggestions and your code the way it is, it is understandable, readable and maintainable by anyone from a Perl novice to a god.

    Update: added bit about checking return value of ``

      A refreshing and totally unexpected tone of reply. I often see comments about more than one way..., but often there does seem to be a preferred way and/or a best practise way.

      I have already read the strict/warnings node and commented in agreement with it (My first post actually). I do use warnings but must admit that I don't tend to use strict. I'm trying to get myself into the habbit of doing so for 'production' code.

      In terms of testing the result of system would something like the below be appropriate?
      if ($var = `system thingy`) || die "Failed to get return from call to system\n";

      Thanks for the comments, encouragment and suggestions.

        Well for me, maintainability should be one of our highest concerns as developers: will the developer who follows me understand my code? But that's probably a good subject for a meditation later!

        You're close with catching the error; this should work:

        $var = `...` or die "System failed: $!\n";

        Basically, you don't need the if; the left hand side of the expression will be undef (false) if it fails, so the or will evaluate the right hand side. You'll see this form of error catching quite a bit, especially when using open and the like to operate on files. Note the use of $!, which will tell you what the system error message was - see perlvar for more information about this.

        Your test is mixing two different kinds of conditional, the 'if' and the 'or' types.

        If/Unless version:

        unless ($var = `system thingy`) { die "Failed to get return from call to system\n"; }

        Or version:

        $var = `system thingy` or die "Failed to get return" from call to syst +em";
        Note the use of 'or' instead of ||. The only difference between them is their precendence, but as a result the 'or' doesn't need the braces round the assignment.

        Overall good coding style. Nice and readable. If all the code I had to do maintenance on was so readable I'd be a very happy bunny.

        Update: Changed the if to an unless since I totally messed up the logic. Oops. Thanks 2mths for pointing that out, shall try and engage brain earlier next time.

        Update: Fixed the missing ` problem. Thanks parv. Also updated brain to test all Perlmonks submissions to avoid silly mistakes like this in future.

Re: Simplifying code (Not obfuscation)
by grinder (Bishop) on Mar 04, 2003 at 11:27 UTC
    #! /usr/bin/perl -w chomp( my $var = `pwd` ); print "You are here -> $var <- in case you were lost\n";

    That is, you can chomp the result of an assignment, because chomp knows how to operate on lvalues.

    I've thrown in the my here to show how you can declare a variable, assign to it, and then chomp it, all in one go. Of course, if your variable is declared earlier (above) in the code then of course you don't have to do that.

    A word of warning, beware of what happens when your system command returns more than one line. For instance, see what happens when you replace pwd with ps. In this case, you can also say:

    chomp( my @proc = `ps` );

    On the other hand, I would spend the time to research what you really want to do. Nobody actually likes calling programs and scraping their output. So much so that you will often find that someone has written a module that gets at the underlying kernel tables or whatever and has published it on CPAN.

    For instance, just the other day I had to do some wholesale disk quota management, and after staring at a few man pages for a while and wondering how I could automate it, a quick search on CPAN revealed the module Quota which did exactly what I needed (and more besides).

    print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
      lvalues = more homework.
      Multiple lines returned... - The norm with NT cmdline tools it seems. I'm sure I can code to cope with that.
      Quota - Sound really interesting, must go and have a look at that!
      CPAN - Doesn't strike me as very Win32 or PPM friendly. As an Win32 dumbo I probably 'scrape' more often that I have to but it saves on dissapointment.
        As for me, I look to CPAN first. If there is something there, chances are that
        • The author put some time in to it (so why should I duplicate his effort, wasting both my time and his)
        • The author put some thought in to it (probably more that I would "hand rolling" a solution)
        • The code is peer reviewed, meaning that gotchas have a better chance to be caught.


        It's always worth checking PPM for the CPAN modules you want - usually there's a PPM version for the less obscure ones.

        Alternatively, some of the monks have their own PPM repositories which further extends the possibilities, see this thread for info.

Too basic a question?
by crenz (Priest) on Mar 04, 2003 at 11:59 UTC

    Others have already commented on your code. I want to comment on your final "wibble".

    I think on PerlMonks, there is no such thing as a question that is too basic. People here are generally very eager to help even absolute newbies. What will displease senior monks and junior monks alike is questions that make clear that the author didn't care to do any research on their own, or does not want to learn, but just wants his or her current problem solved.

    However, your post shows that you have put some thought into your question before stating it, even if it is basic, and that you are eager to learn. So don't be fearful to ask more basic questions, you are welcome!

    Another aspect of "basic" questions is that a lot of them are not basic at all. They might touch on a hidden aspect of perl that many people are not aware of, and thus be much more edifying than you imagine.

      Your post hits many a chord with my newfound current thinking. The response to this post has been phenomenal (IMHO) and massively more beneficial than I ever invisaged.

      It seems that by going 'back to basics' my preconceptions and assumptions don't come into play and therefore I get much better responses. Ie, I ask a better question and benefit greatly from doing so.

      I have to say that generally I'm not in favour of people asking basic questions (Before anyone comments I recognise that I'm highly intolerant and a hypocrite) if I think they could have got the answer by doing a little reading or thinking themselves. That said I think you have made good comments on the 'basic and genuine' vs 'basic and lazy'. And have caused me to reform my views.
Re: Simplifying code (Not obfuscation)
by theorbtwo (Prior) on Mar 04, 2003 at 11:15 UTC

    First thing: Don't put double-quotes around $var in your print. What you have written takes the string value of $var, and then prints that. It would have exactly the same effect to simply print $var (IE no quotes). (If that were a return instead of a print, there would be differences, in that if $var had some meaning beyond it's stringification (was an object, for an example), it would destroy that value.) Using quotes will actualy slow your code down, and make it not do the right thing, in almost all cases. (Well, in almost all cases where the only thing in the doublequotes is a single variable.)

    I was going to write more here, but doubtless others will. I need to get going.

    Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

      Point taken and generally understood. Further digestion of finer points probably required. Guess I need to go learn about return now.

      Thanks for taking the time to put something. I do appreciate that it's easier to 'think' about a reply that to 'write' one. Which is why I try to make the effort to comment and thank those that do manage to 'write'.
Re: Simplifying code (Not obfuscation)
by PodMaster (Abbot) on Mar 04, 2003 at 10:31 UTC
    perl -le"chomp($_=`echo butter`);print"

    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    I run a Win32 PPM repository for perl 5.6x+5.8x. I take requests.
    ** The Third rule of perl club is a statement of fact: pod is sexy.

      Golf!! :) perl -le'$_=`echo butter`;chomp;print'

      -- Hofmator

        What's the point in chomping if you only going to put it back with -l?

        perl -e"$_=`echo butter`;print"

        but that becomes

        perl -e"print `echo butter`"

        but hang on, we can simplify that further

        echo butter

        Oh dear! Now I've done away with the need for perl altogether, which means this thread becomes off topic and is reaper bait:)

        Levity aside, I think the OP's question really comes down to "Why can't I do..."

        print chomp( `some system command` );

        Which is certainly something I have tried more than once, and the only answers I have come up with, and there is probably better wisdom on this kicking around somewhere, is that if chomp returned the result of the thing it chomped, then

        chomp(@lines) would have to become

        @lines = chomp(@lines) which would be less efficient.

        and if you used it in a while loop

        while(my $line = chomp(<>) ) { #do stuff; }

        The loop would terminate early on zero-length blank lines as chomp would return '', which would test false.

        Examine what is said, not who speaks.
        1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
        2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
        3) Any sufficiently advanced technology is indistinguishable from magic.
        Arthur C. Clarke.
        0123456789012345678901234 perl -le 'print`echo foo`=~/(.*)\n/' __output__ foo
        This of course assumes you're only expecting a single line of output, isn't hugely portable and the golf score also depends on the system call.


      Thanks & WTF?! :-)

      Me thinks some time studying this is required. If this isn't an example of obfuscation I don't think I'd want to see one.

        Just in case you don't realise what was meant.. Golf is where Perl programmers try and get a reasonably simple task completed in the least number of (key)strokes. As such it's not quite obfuscation, but it's a very close relative.

        Golfing in everyday code is generally a very bad thing as it results in Perl that consists of streams of delicate logic which are very unreadable, and even less maintainable.