http://qs1969.pair.com?node_id=403540


in reply to Functional Programming & method rewriting

You made things more complicated than they need to be. Try this:
#!/usr/bin/perl use strict; sub prefix_later { my ($just_once, $and_later) = @_; my $ct = 0; return sub { $and_later->(@_) if $ct++; $just_once->(@_); } } my $hi_mom = prefix_later( sub { print "You said: ", shift, "\n"; }, sub { print "You've already said: ", shift, "!\n"; } ); $hi_mom->("hi mom") for 1..3;
Output:
You said: hi mom You've already said: hi mom! You said: hi mom You've already said: hi mom! You said: hi mom
Why type more than you need to? And what where you doing with my (@args) = shift();?

Replies are listed 'Best First'.
Re^2: Functional Programming & method rewriting
by SpanishInquisition (Pilgrim) on Oct 29, 2004 at 00:15 UTC
    Yep, that is an good refactoring of prefix_later. The double closure, yeah, that's overkill, I did it just because I could. Code debate on a "I'm just screwing around" thread? :) Ok, I'll bite...
    Why type more than you need to?

    This philosophy is one I don't agree with, especially when developing code you are going to have to go back and tweak later. While I hate typing way too much (java boilerplate and convention is disgusting), I do type VERY VERY fast. Many of my habits are those of pseudo-defensive programming. Even when I'm not writing "throw away" code, I don't let go of those habits easily. Why? I don't write much throw away code ... I tend to work on stuff that sticks around.

    For instance (and this is just me), I *always* name my subroutine parameters and never use "shift" directly. Why? I'm being defensive because I usually want named parameters later. Every time I've done a quick shift in the middle of a block of code, I've had to go back and change it later. With @args, I might want to later replace that @args with ($gorp,$slug,@args) = shift() for instance. It leaves a place in the code to do that, and I only have to edit one line to make that change.

    But I think after that double closure you can grill me all you want :) It's like climbing Mt. Everest ... "Why? Because It's There".

      Why type more than you need to?
      This philosophy is one I don't agree with, especially when developing code you are going to have to go back and tweak later.
      You're right. And I asked the wrong question; or at least an incomplete one. What I meant to ask was: why type more when you're not gaining anything? Your code is more complex, it's partially duplicated, and it's not very readable. I consider myself a strong Perl programmer (and I realize that assumption can be a dangerous one to start with :-), and I had to sit for a minute before I could figure out what it was that you'd done.
      Every time I've done a quick shift in the middle of a block of code, I've had to go back and change it later. With @args, I might want to later replace that @args with ($gorp,$slug,@args) = shift() for instance. It leaves a place in the code to do that, and I only have to edit one line to make that change.
      Are you sure you don't mean my (@args) = @_;? shift only ever returns one element, so using it in list context is pointless: ($gorp,$slug,@args) = shift() doesn't do anything to $slug or @args.

      I don't mean to grill you. I just want to understand and give some (hopefully friendly) advice.

      Update: my 200th node! :-)
        My fault. Ok, so replace ($gorp, $slug, @args) = shift() with ($gorp,$slug) = @_ and you get what I meant, ah well. Please shoot me for only testing with functions taking a single parameter :)

        This stupid mistake of mine was related to me thinking @_ would be accidentally closed around the first block, which isn't true, because @_ is magic... (I was always using @_ before, so, umh, that's why it's odd).