Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: Using $_ as a temp var, especially in functions

by BrowserUk (Patriarch)
on Oct 23, 2002 at 12:05 UTC ( [id://207364]=note: print w/replies, xml ) Need Help??


in reply to Using $_ as a temp var, especially in functions

Personally, if an intermediate var is used is in more than one line of code (or possibly two), it no longer warrents the nomenclature "temporary". At some point in the future, someone (possibly you:) is going to come along and insert some code between some of the lines where the 'temporary var' is used and that seperates it from its temporaryness (Is that a word?).

In any other language I've used, my advice would be to just go ahead and use a locally-scoped (lexical in Perl terminology ie. my $tempSomething). However, the propensity (and utility) of Perl's built-ins to use $_ leads to a slightly ambiguous decision, in that I do use $_ where that makes sense because I am going to apply one or more built-in features which default to that.

However, I wouldn't use the for ($thingToAlias) { ... }; as I personally find the one-time-loop construct distracting. In preference I would use a bare block.

{ ## Updated: The next line was (erroneously) local $_ = $thingToAlias, local *_ = \$thingToAlias; ##which [Aristotle] pointed out *doesn't* alias m/regex1/; s/regex2/modification/; #other stuff }

To me (who is still experimenting and evolving my Perl Style), this has all the advantages of the 1-time for with none of it's disadvantages. It will be interesting to see if anyone has any arguments against this.


Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!

Replies are listed 'Best First'.
Re: Re: Using $_ as a temp var, especially in functions
by TimToady (Parson) on Oct 23, 2002 at 23:19 UTC
    The biggest argument against it that I can see is that the for will probably be translated to a given in Perl 6, while your local probably wouldn't.

      Interesting point. I hadn't considered Perl 6, I'm trying hard not to get excited about until it's a little closer to fruition.

      When you say "the for will probably be translated to a given", do you mean by an automated process? Is there an intention to provide a p5top5.pl or binary? I thought that the route was to have a p5 'mode' rather than conversion?

      Given all the different ways the scalar value in the for loop could be provided

      for ($scalar) {...} for (funcReturningScalar()) {..} for ($hash{of}{some}{arbitrar}{size}{returning}{scalar}) {...} for($$hash{returning}{refToScalar}) { ... } # Many more

      Unless this p5top6 processor is going to act at the bytecode level, its going to have to be a fairly sophisticated piece of code to catch all the possible variations where the topicaliser of the for returns a scalar and not a list? Would it be that much more work to have it check to see if the first line inside a bareblock was local $_ = expression; which by definition must be assigning a scalar?

      Thinking about this further, I'm not sure I understand though. As given is a case-type construct, converting a one-time for to a given would result in some strange code

      for ($scalar) { # do stuff; }

      Becoming

      given ($scalar) { when <<always>> { # do stuff; } }

      I'm not quite clear how you would express the always? Though I assume given will have an equivalent of C's default: clause, so I guess it could become

      given ($scalar) { default { # do stuff; } }

      But I'm not sure that's much better.


      Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
Re^2: Using $_ as a temp var, especially in functions
by Aristotle (Chancellor) on Oct 24, 2002 at 02:25 UTC

    There is a very significant difference: your second snippet isn't aliasing anything, it's making a local copy.

    I tend to use for as a topicalizer for single expressions, as a statement modifier. It would be cumbersome to bloat those into a naked block with a local, and will often not even do what I want since I'm actually intending to change the original variable. A silly example would be s/nit// for $style;

    For temporary variables, which was what this thread really was about, I use local. Not only does a for block not do what I want anyway (except (close your eyes) in the perverted for(my $temp) { ... } form (now open them again)) because it aliases a variable rather than give me a fresh, empty one, but it also adds another indentation level, which in my stylistic preference is to be avoided at all cost.

    for and local are really orthogonal to each other. Neither can do what the other does, and so debating which one is preferred is moot.

    Makeshifts last the longest.

      second snippet isn't aliasing anything

      Good point. It would have to be

      $_= 'value before localising'; my $thingToAlias = 'the quick brown fox'; { local *_= \$thingToAlias; s/brown//; } print $thingToAlias; print $_;

      Giving

      C:\test>test the quick fox value before localising C:\test>

      A silly example would be s/nit// for $style;

      I can't see any advantage in this over $style =~ s/nit//;?

      I appreciate this was just a trivial example, but I can't see where this would be useful as a statement modifier? (No doubt you have a great example up your sleeve:^)

      For temporary variables, which was what this thread really was about, I use local. Not only does a for block not do what I want anyway (except (close your eyes) in the perverted for(my $temp) { ... } form (now open them again)) because it aliases a variable rather than give me a fresh, empty one, but it also adds another indentation level, which in my stylistic preference is to be avoided at all cost.

      for and local are really orthogonal to each other. Neither can do what the other does, and so debating which one is preferred is moot.

      Agreed. They are unrelated, but I was responding to Re: Using $_ as a temp var, especially in functions in the second part of my post rather than the OP.

      I first saw the 1-time for when you showed it to me in a thread about a week ago (which I can't now find?) but I was uncomfortable with the idiom of using a loop for a straight through peice of code. I'm similarly troubled by the use of redo in a bare block or if statement, prefering to see a loop construct where things are going to loop.

      I did spend a while after you first showed me the 1-time for looking for a suitable alternative. And came up with the local *_ = \$variable; (Which in turn was stolen from the Cheap idioms thread.), but promptly forgot the detail as I haven't had a need to use it yet. That's also why I was interested in the arguments against it.

      Who knows, maybe in time I'll get used to these idioms as I have others and go with the flow (sic), but as I said, my devlopment of a personal style, and my investigations of what's possible in perl is ongoing.


      Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
        You are right, that example is silly, which is why I said so. :^) It's useful (as that thread was discussing btw) for something like $_ eq "pot" and ($_ = "kettle") for $some->{deeply}{nested}{data}{structure}; The straight alternative is
        $some->{deeply}{nested}{data}{structure} = "kettle" if $some->{deeply}{nested}{data}{structure} eq "pot";
        which irritates my hubris. Localizing here is better than that, but it's just too much red tape for my taste:
        { local *_ = \$some->{deeply}{nested}{data}{structure}; $_ = "kettle" if $_ eq "pot"; }

        local *_ = \$something; is not a language construct, I have to brainparse it and understand what's going on to read the code.

        I see where you object to a loop that has only one iteration, although I find the use of redo in a naked block far worse than a single-iteration for loop: the redo conceils the loop character because you don't know that that naked block is one until you read to an arbitrary point inside it. for used as a topicalizer on the other hand makes it immediately obvious that we're only looking at a single iteration.

        The example you gave where a function's return value is topicalized misses the point. You topicalize a variable when you intend to modify it - doing that to a function return value you haven't saved is pointless. You might of course do something like this:

        my $stuff; for(return_value()) { chomp; s/foo//g; tr/x/y/; $stuff = $_; }
        But if I had to maintain that I'd hunt you down and kill you. That obviously should have been
        my $stuff = return_value(); for($stuff) { chomp; s/foo//g; tr/x/y/; }

        For the record, I actually don't use the long construct with the for block frequently either. It does come in very handy when it's appropriate though. (I got the idea of using for as a topicalizer from the man himself actually - he mentioned this in an interview, where he said it Perl has a topicalizer, for, which lets people say "it", ie $_, without specifying the subject over and over.)

        That's what I have to say on the issue. YMMV :-)

        Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://207364]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-26 04:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found