Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Doing "it" only once

by Limbic~Region (Chancellor)
on Sep 21, 2005 at 15:08 UTC ( #493826=perlmeditation: print w/ replies, xml ) Need Help??

All,
There was a recent post on the Perl6 Language mailing list asking if there would be a way to identify code as "do it once only". Here is an example.
while ( <FH> ) { next if $_ eq 'foo'; # Where foo can only appear once in the file print; }
Once the match has been made, why must every subsequent line in the file be tested? I have also desired this ability in long tight running loops when performance was a concern and tried to figure out a way to make it work. I came up with the following inelegant code:
#!/usr/bin/perl use strict; use warnings; do_something(5); sub do_something { my $target = shift; my $block; my $block2 = sub { print "No need to check $_ against $target anymore\n"; }; my $block1 = sub { if ( $_ == $target ) { print "Skipping $target\n"; $block = $block2; } else { print "$_ is not $target\n"; } }; $block = $block1; for ( 1 .. 9 ) { $block->(); } }
Once the condition has been met, the code dynamically changes to no longer check for the condition. Keep in mind, to get this luxury I am now paying for the overhead of dereferencing and invoking a sub each time to get this "performance" benefit.

I was wondering what your thoughts on this are? If you think of running code as a work flow and each piece of functionality a widget then what we are talking about is a special kind of widget that can replace another widget while the work flow is running. Would building this functionality in the Perl 6 core be of great benefit? Obviously providing the functionality would open the door for other applications then just the "run once" feature. If this ability existed with negligible costs - what other things could you think of to do with it?

Cheers - L~R

Update: I removed some irrelevant pieces of the code which were leftover from my trial and error attempts

Comment on Doing "it" only once
Select or Download Code
Re: Doing "it" only once
by japhy (Canon) on Sep 21, 2005 at 15:18 UTC
    I once thought of this concept, but I too feel the work-around is too much work for me and for Perl. It feels to me like the sort of thing the /o modifier does for regexes: we need to be able to change the op-tree at a much lower level.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Doing "it" only once
by cog (Parson) on Sep 21, 2005 at 15:18 UTC
    Is it me, or wouldn't

    while ( <FH> ) { last if $_ eq 'foo'; # Where foo can only appear once in the file print; } while ( <FH> ) { print; }

    do the trick? (in this situation, of course)

      cog,
      Yes of course, in this situation. The reason it works is because file handles are iterators remembering where they left off and because our condition was simple. There are far more situations in which it wouldn't work so the meditation is on the idea of dynamically splicing in code blocks while code is running and what neat things might you do if the functionality existed without heavy penalties.

      Cheers - L~R

        Eh, I've a hard time believe there exists a situation where it [statically splicing the code, as in cog's solution] wouldn't work, but where it's still possible to dynamically splicing in code blocks while code is running.

        Could you give an example of such code?

        BTW, what you are asking for is a special case of "loop enlightment", and cog's solution is the standard way of solving this. It belongs in Programming 102.

      Indeed there are not unexpectedly many WTDI. As the author of the original post in p6l, I must say that Limbic~Region is one of the few that seem to have authentically understood the real point of the issue and in his much better phrasing than mine it all boils down to the hypothetical possibility of modifying the optree at runtime.

      Now, BrowserUK informed us here that this kind of code self-modification was very common in early languages, but also regarded as a horror, which is one of the reasons that led to structured programming and later to OO programming, etc. OTOH it has become common again, in FP languages, as a compiler optimization.

      But then it's hard to think that in such a dynamic and multi-paradigmatic language like Perl, be it 5 or 6, something exactly along these lines could be done. So my question, in the context of Perl6, regarded the possibility to do so by means of some syntactic sugar visually distinctive enough to avoid an unintentional use of it and to make clear what that the one using it wants and at the same time cheap enough, type-wise, to make it preferable over any of the already proposed alternatives.

      Now, wrt you code above:

      while ( <FH> ) { last if $_ eq 'foo'; # Where foo can only appear once in the file print; } while ( <FH> ) { print; }
      it obviously looks nice enough and it makes clear why you're doing so. But it's still nearly double the code that one conceptually could want. Not only: if print were really a longer portion of code, you may {want,need} to refactor it into a sub, with the added overhead of a sub call (and here we're being -for once- really paranoid 'bout efficiency and micro-optimizations), which would not have been necessary at all if we had that kind of syntactic sugar...
        Not only: if print were really a longer portion of code, you may {want,need} to refactor it into a sub, with the added overhead of a sub call (and here we're being -for once- really paranoid 'bout efficiency and micro-optimizations), which would not have been necessary at all if we had that kind of syntactic sugar...
        Well, that would ask for syntactic sugar with an overhead of less than a subroutine call....

        Note that with clever use of string eval you can duplicate the code without having to maintain it twice, and not have the overhead of calling a subroutine from a loop. And you can move the eval as far out as you want (so the overhead of calling it becomes small enough).

Re: Doing "it" only once
by jdporter (Canon) on Sep 21, 2005 at 15:19 UTC
    I usually handle it this way:
    while ( <FH> ) { last if $_ eq 'foo'; # Where foo can only appear once in the file print; } while ( <FH> ) { print; }
    Of course, if print is really something more, extract it to a subroutine.
      jdporter,
      The first part of your response is identical to cog's. I will refer to my response there. I am pretty sure your last comment still only works in the most trivial of cases. Consider:
      • Restarting most loops requires knowing where the previous left off
      • Having more than 1 "run this once" statements complicates things dramatically - especially if order is unknown
      • The "run this once" condition might not always be skipping to the next iteration in the loop
      I am sure there are more and the point of the medidation isn't to enumerate them. Just assume for a second that the functionality existed and by some magic it didn't cost much - what would you do with it?

      Cheers - L~R

        Understood. But neither your (trivial) example motivating problem, nor your proposed solution, addresses any of those points either. So I don't quite grep why you have any issue with my/coq's answer.

        Why don't you post a real-world problem that has all of your bulleted issues above, and then post a real-world solution for that problem?

Re: Doing "it" only once
by 5mi11er (Deacon) on Sep 21, 2005 at 15:19 UTC
    I've had this type of thought running through my head relatively recently, but it wasn't nearly as well "defined" as this, nor did I pursue the idea as you have.

    I think the problem is going to be the "negligible cost". Without unrolling the loop internally, you'd still be forced to evaluate an if, unrolling the loop adds complexity etc.

    Thanks for the snippet anyway, whether or not it is actually worth the trouble, it's still a nice trick.

    -Scott

      After spending nearly half of my votes on this thread this morning, I'd contemplated updating the node above; but I also wanted to further comment, thus I'm adding this node.

      When I originally replied above, optree modification had not entered my mind. However, that option is certainly no less complex than unrolling the loop. At first glance it seems like that optree modification might be the answer, but as the code example to do that by diotalevi shows, its not trivial.

      I think QM's post below is an excellent summary of this thread and the [good] ideas presented.

      -Scott

Re: Doing "it" only once
by dragonchild (Archbishop) on Sep 21, 2005 at 15:22 UTC
    I agree that this kind of functionality would be way cool. However, it sounds like you want to do on-the-fly rewriting of the optree. I'm not certain that this is possible in the general case, given optimizations that would probably benefit you more than your optimization is going to.

    You could do something with overload instead of subrefs. I'm not sure how much faster this will be, but here goes:

    package Always::False; use overload 'bool' => sub { return; }; sub new { return bless \(my $foo), shift } package Check::Once; use overload 'bool' => 'boolify'; sub new { my $class = shift; my ($val) = @_; return bless \$val, $class; } sub boolify { if (${$_[0]} eq $_) { $_[0] = Always::False->new; return 1; } else { return; } } package main; my $once_only = Check::Once->new('foo'); while (<FILE>) { next if $once_only; # Other stuff here. }

    Yes, there are improvements that could be made, but it's just proof-of-concept.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: Doing "it" only once
by Corion (Pope) on Sep 21, 2005 at 15:33 UTC

    How is what you want to do different from the last keyword? Or is your goal to make multiple such checks "optimally efficient"?

    while (<DATA>) { if (/foo/) { print "Found 'foo'\n"; }; if (/bar/) { print "Found 'bar'\n"; }; if (/baz/) { print "Found 'baz'\n"; }; print "Unknown line: $_"; }; __DATA__ foozle bazzle barren

    If you want to reduce the loop size without paying a high syntactical tax I would use the following:

    my @items =( sub { /foo/ and do { print "Found 'foo'\n"; }}, sub { /bar/ and do { print "Found 'bar'\n"; }}, sub { /baz/ and do { print "Found 'baz'\n"; }}, sub { print "Unknown line: $_"; undef }, ); my @current = @items; while (defined (my $line = <DATA>)) { my @remaining = @current; @current = (); local $_ = $line; CODE: while (my $c = shift @remaining) { if ($c->()) { push @current, @remaining; last # CODE } else { push @current, $c; }; }; }; __DATA__ foozle --- #1 bazzle --- #2 barren --- #3

    The driving loop should likely be hidden away in some module. But the whole thing is suspiciously close to Switch.pm anyway, and I (without benchmarks) doubt that an optimization like this will buy much unless the single tests are very expensive, as the subroutine calls are "expensive" too and the loop and anonymous subroutines make things harder to debug. And you need to make sure that all match routines return a true value when they actually matched

      Corion,
      This specific case relates more to the next keyword than to last. The idea is that once a particular piece of code has been invoked, it magically disapears.
      for ( 1 .. 100 ) { next if $_ == 50; print "$_\n"; }
      Becomes functionally equivalent to print "$_\n" for 1 .. 49, 51 .. 100;. The meditation isn't about solving for specific cases but having the ability to dynamically change the running code and what would you do with it if it were cheap.

      It really isn't like a source filter because you want the code to first be there and then go away while the code is running. I am already pretty sure that there is no way in the existing language to get this optimization without paying more for it then you get out. That's not what the medidation is about though.

      Cheers - L~R

      It quickly becomes apparent that a generic solution to the general problem is a state machine, and that such a generic solution is (or could be) an interpreter of a regular language. (This is taught in (approximately) CS 440, though the principles are introduced earlier than that.)
Re: Doing "it" only once
by BrowserUk (Pope) on Sep 21, 2005 at 16:27 UTC

    Your code looks overly complicated, it could be as simple as:

    #! perl -sw use strict; sub doit { local $^W; *doit = sub{ print } if m[^foo]; } doit() while $_ = <DATA>; =output P:\test>junk4 fum fiddlesticks =cut __DATA__ fee fi foo fum fiddlesticks

    It's this kind of self-modifying code that horrified the CS types in the late 60's (early COBOL compilers used this extensively), and is what lead to 'structured programming' and eventually object orientation.

    The funny thing is it is exactly this kind of technique that allows FP language compilers to produce efficient code from what appears horribly inefficient at the source code level. Goggle for a paper on the "The spineless tagless G-machine" for further reading.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      BrowserUk,
      I am sure there are many ways to improve the specific example and thanks for providing one of them. I didn't spend a lot of time thinking about it as I was just trying to provide a proof-of-concept so people would get an idea of how it might work.

      Additionally, thanks for the history lesson. In a nutshell, this type of functionality has been intentionally removed from some languages so these types of optimizations wouldn't happen - interesting.

      Cheers - L~R

        ...this type of functionality has been intentionally removed from some languages so these types of optimizations wouldn't happen...

        Yes, but as I said, FP language compilers are now making a virtue of it :)

        The very thing that makes porting FP techniques into Perl such a waste of time, is that Perl cannot hope to come close to performing anything like the depth of analysis (at runtime) that (say) the GHC can perform at compile time. For example, memoization may seem like an 'advanced technique' in Perl's terms, but when you consider that every single function in Haskell is automatically memoized by the compiler, and moreover, every parameter of every function (currying) also. And this is done such that once a function is called with a given (set of) parameter(s), the code to call the function is actually overwritten with the resultant value, you begin to see how the efficiency is achieved.

        The mechanism of overwriting the function invocation with the value means that once the function has been called, every single subsequent call of the function (with the same parameter(s)) throughout the program, now simply retrieves the value of the result. And this is done such that there is not even a conditional test, never mind additional function calls to implement the memoization as is required by some Perl implementations.

        It is the referential integrity built in to the Haskell language that allows GHC to analyse the entire program structure and perform extensive graph reduction with value substitution.

        The dynamic nature of Perl, the need for introspection and the need to support mutable data, make many of the optimisations possible in FP languages, impossible in Perl.

        It would be nice to think that P6 would be able to detect the (referentially pure) conditions that would allow it to substitute value for function calls after the first invocation, but it will require some extremely clever code in the compiler/interpreter to perform that trick.

        In terms of Perl 5, it actually make more sense to model the function invocations in terms of a tied hash. The code just uses the appropriate value of the hash $fp{ parameter }, and the tie mechanism fills in the value if it isn't already present. Subsequent calls for the same value are very efficient (pro rata the inefficiency of tied hashs).

        You end up with a lazy (never calculated if never called for), strict (only calculated once), and very perlish mechanism that is a much better fit with the language that some others that attempt to emulate the source code semantics of FP languages without recognising that the absence of the optimising compiler renders them horribly inefficient.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Doing "it" only once
by sauoq (Abbot) on Sep 21, 2005 at 16:44 UTC

    Flags aren't always a bad thing.

    while ( ... ) { if (!$flag && check_whatever()) { do_whatever(); $flag = 1; } }

    I'd suspect that the best way of putting this into the core would be simply by setting/checking a flag at the C (or Parrot, I guess) level instead of the Perl level. I suppose that, after a single execution you could actually remove the relevant ops from the tree altogether, but I'd have to wonder at the efficiency of that in all but very long running loops.

    Making it a language feature in Perl 6 might make some sense as it would allow the programmer to avoid the use of flag. I don't see the point in jumping through any hoops to implement this in Perl 5 though.

    -sauoq
    "My two cents aren't worth a dime.";
    
      Flags aren't always a bad thing.

      They are if you choose a terrible name :)

      while ( ... ) { if ( !$done_whatever && check_whatever()) { do_whatever(); $done_whatever = 1; } }

      There, I feel much better now.

      • another intruder with the mooring in the heart of the Perl

Re: Doing "it" only once
by rnahi (Curate) on Sep 21, 2005 at 18:14 UTC

    Perhaps not what you're after, but there is an interesting discussion on something similar at A TRUE-once variable.

Re: Doing "it" only once
by ambrus (Abbot) on Sep 21, 2005 at 19:21 UTC

    There's also a shortcut: the flip-flop operator:

    while (<>) { if (1 eq (/foo/ .. (1x0))) { do_something(); } }
    this will not check for /foo/ once it's found.

    Of course, this is not any better than

    my $found; while (<>) { if (!$found && /foo/) { $found++; do_something() } }
      The shorter cut is the match only once operator that is built-in to Perl.

      Caution: Contents may have been coded under pressure.

        Sure, but that works only for a regexp, not for any condition.

Re: Doing "it" only once
by diotalevi (Canon) on Sep 21, 2005 at 19:55 UTC

    This is "easy enough" if you consider the problem as the function ONCE() alters the optree of the function that calls it so that the scope that contained it is edited right out. Why not, I suppose.

    sub foo { if ( 1 ) { ONCE(); # This block is run only once, ever. } } use Devel::Caller 'caller_cv'; use B 'svrev_2object'; use B::Utils qw( walkoptree_filtered opgrep ); use B::Generate (); sub ONCE { walkoptree_filtered svref_2object( caller_cv 1 )->ROOT, \ &find_ENTERSUB, \ &removE_ONCE; } sub remove_once { # Remove the parent of this op from execution. my $op = shift; my $parent = $op->parent; # This ignores other nodes which might point to this one using ->o +ther(). $parent->previous->next( $parent->next ); # Remove $parent from the family tree. my $grandma = $parent->parent; if ( ${$grandma->first} == $$parent ) { $grandma->first( $parent->sibling ); } else { for my $aunt ( $grandma->kids ) { if ( ${$aunt->sibling} == $$parent ) { $aunt->sibling( $parent->sibling ); last; } } } } sub find_ENTERSUB { # I have no idea if this is the *right* ONCE() to remove. my $op = shift; # perl -MO=Concise -e "foo()" # (entersub # (pushmark # (ex-list # (pushmark) # (gv "foo")))) opgrep { name => 'entersub', first => { first => { sibling => { first => { PV => 'foo' + } } } } }, $op; }
Re: Doing "it" only once
by rje (Deacon) on Sep 21, 2005 at 20:27 UTC
    It's almost like you'd want a sort of an "event"-driven system where the handlers de-register themselves when they get triggered N (N==1 in this case) times, isn't it?
Re: Doing "it" only once
by QM (Vicar) on Sep 21, 2005 at 23:05 UTC
    I might as well wade into the fray, and show TIMTOWTDI in Perl5...

    How about a function table where the entries remove themselves once they're no longer needed?

    Once there is no more code that would pass the conditionals, the loop exits.

    (BTW, what keeps the world from imploding when the current sub is deleted from the function hash? There must be a referent lying around somewhere until the sub exits, right?)

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Re: Doing "it" only once
by Juerd (Abbot) on Sep 22, 2005 at 09:01 UTC

    Supposing there is a way to pause (pause) a loop, and continue it later (cont { ... }), it's easy:

    my macro do_something { ... } for (...) { pause, next if ...; do_something; } cont { do_something; }
    For this to work, pause would only come into effect after the entire statement is evaluated. Alternatively, consider next :pause or pause :next.

    Having things optimized with a simple hint I think would be trivial.

    for (...) { notagain, next if ...; ...; }
    would automatically be split.

    Still, I don't think it's a problem that needs fixing. If you want to fix it, it's probably simple enough to do it in a module.

    I would like the pause/cont combo, though. For many purposes, because not everyone likes to think in iterators.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

      for (...) { notagain, next if ...; ...; }
      Could notagain be a sort of macro that would turn this code into that above -- or better: taking into account that there may already be a cont block, "inject" some code into a suitable "hook" provided by the latter (which I would definitely expect to be there).
Re: Doing "it" only once
by Anonymous Monk on Sep 22, 2005 at 11:01 UTC
    #!/usr/bin/perl use strict; use warnings; my @labels = qw /L0 L1 L2/; while (<DATA>) { chomp; goto $labels[0]; L0: if (/foo/) { print "FOO!\n"; @labels = grep {$_ ne "L0"} @labels; next; } goto $labels[1]; L1: if (/bar/) { print "BAR!\n"; @labels = grep {$_ ne "L1"} @labels; next; } L2: print "$_ "; } print "\n"; __DATA__ one two bar three four foo five six foo seven eight bar nine ten one two BAR! three four FOO! five six foo seven eight bar nine ten
      my @labels = qw /L0 L1 L2/; ... goto $labels[0]; L0:
      Hard to code and maintain. You want a construct that works correctly without depending on you getting all of the labels correct, or selecting the proper index in the labels array. Your code has 3 places that have to "match" to function.

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

        You want a construct that works correctly without depending on you getting all of the labels correct,

        Sure, once you start writing code that works correctly without depending you getting all the subroutine names correct.

        selecting the proper index in the labels array.

        Well, it's not very hard to count 0, 1, 2, .... ;-)

Re: Doing "it" only once
by QM (Vicar) on Sep 22, 2005 at 13:47 UTC
    In my frenzy to chase down novel (to me) ideas, I neglected to comment on L~R's main point, which I'll immodestly restate as:
    What if Perl had a language construct for "Do this only once"?
    (We can argue about whether this should be "once" or "N times".)

    The core idea is once the test fails, it's removed from the optree.

    What would we use for syntax?

    once (/foo/) { print "I've seen foo\n"; }
    or more often
    once (my $i;/foo/;$i++ < 42) { print "I've seen foo $i times\n"; }
    Would it be useful? It seems it's only merit is in speeding up tight loops, where even checking a boolean is noticeable.

    Would it cause bugs? Yes, definitely. There would be a cargo cult of "Use once to optimize conditionals", when very few situations actually benefit from it.

    Is it more convenient than anything existing? Yes, indeed. I have yet to see anything that approaches the efficiency of once.

    I'll be interested in seeing if this idea catches fire, implemented, and how many bugs it generates.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      If you rework this as actual perl code, its even possible to do today, with no changes to the perl parser. Really though, Limbic~Region should just be using lisp if he wants to have such flexibility. If this is too much overhead, the ifonce() function could be inlined like I described in my other node.

      sub ifonce { my ( $test, $block, $else ) = @_; if ( $test->() ) { $block->(); # Perform the appropriate B magic to remove this function call + from execution. } else { $else->(); } }
        diotalevi,
        I never said I was for or against this functionality, but why shouldn't it be considered for inclusion in Perl6? While I have already had this conversation with you in the Chatterbox, I believe it is worth repeating here for the sake of others.

        The meditation is about the possibility of Perl6 having the ability to modify the optree (or its equivalent) while it is running as core functionality and what you would do with it if it were available. The majority of the monks have missed this because they apparently focused on the code and didn't bother reading the commentary.

        You have stressed that you think I should learn Lisp before asking such questions and I would argue that you should read what I wrote and not assume to know what I was musing about. I respect you and your abilities a great deal, but I am probably going to come off sounding like a jerk. Regardless of our differences in opinion - thank you for your contributions.

        I know that there are many ways of achieving the same functionality currently and even included an example. Perhaps that was my downfall. People have been so eager to point out more ways or to recommend using another language that they have failed to see the forest through the trees.

        I was taught in school that the final paragraph should always bring the point you are trying to make home. I think I did that and have no explanation as to why so many people missed it.

        Cheers - L~R

      The keyword 'once' is very misleading. We're talking about optimizing away checking of a conditional - but it's not true that this conditional is checked only once. It continues to be checked (and needs to be checked) until it happens to be true.

      Perl6 will have a FIRST block, meaning the block will be executed only once, and to be specific, the first time the surrounding block was entered. If you write this:

      while (...) { if (/foo/) { FIRST {...; next} } ... }
      and perl can determine there are no side-effects in the conditional, perl could be made to optimize away the conditional once it was true once.

      Having said that, the original problem isn't clearly defined. Suppose there would be this 'once-only if', what should the following print:

      my @list = qw /foo bar foo/; for my $x (1, 2) { for (@list) { if (/foo/) { # Assume a 'once-only if' print "foo"; } } }
      Should it print 'foo' once, or twice? That is, is the "once-only" a property of the enclosing loop, to be reset when that loop is reentered, or a property of the condition itself, meaning that after it became true once, it will never be true in the life-time of the program?
        That is, is the "once-only" a property of the enclosing loop, to be reset when that loop is reentered, or a property of the condition itself, meaning that after it became true once, it will never be true in the life-time of the program?
        Good point. I wonder if we could make a parallel with the our/my distinction, such that a my once would reset each time the enclosing block is entered, but our once would not? Or perhaps some sort of reset operator, along with labels, to reset a once conditional.

        Seems to be a lot of possible paths there. We should probably agree on the fundamental property first. I see a few choices:

        1) a conditional, once true, never tested again
        2) a block, once entered, never entered again (including testing for any attached condition).
        3) a statement modifier, indicating the attached block will only be executed once.

        And then further choices about whether it's resettable, and the reset mechanism. [I can imagine taking the language duality of "once" as eleven in spanish, and having it context or parameter sensitive. If it's true 1 time, it's pronounced "wuns", if it's reset, it's pronounced "on-say".]

        Lots of potential. Still, is it useful? Is it practical? Or is it just cool?

        Update: Clarified (2) to be more general than (1).

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

Re: Doing "it" only once
by Jenda (Abbot) on Sep 22, 2005 at 16:17 UTC

    What's the scope of your ONCE? Or rather how would you specify what is the scope?

    Suppose you had a code like this:

    for my $file (@files) { open FH, '<', $file or die "$!\n"; while ( <FH> ) { next if $_ eq 'foo'; # Where foo can only appear once in the file print; } close FH }
    How do you expect to be able to specify whether the 'foo' is supposed to appear only once in each file or just once during one invocation of the script? Keep in mind that if it was the first case you definitely can't rewrite the optree. Except if you rewrote it so that it would rewrite itself to the original state at the loop's end.

    And actually ... what is the loops end? Suppose the code is in a subroutine and that subroutine is called recursively by the code in the loop. Now the optree of the "outer invocation" should look like this and the optree of the "inner invocation" like that? This way lies madness if you ask me.

    If the condition is expensive, use a flag. You can scope the flag variable any way you need and I would definitely not worry about the penalty caused by evaluating a scalar in bool context and executing a single AND instruction. That's negligible in all but the tightest loops.

    Jenda
    XML sucks. Badly. SOAP on the other hand is the most powerfull vacuum pump ever invented.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (8)
As of 2014-12-27 01:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (176 votes), past polls