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

DWIM Part Nineteen: Unary Operators in Void Context

by CheeseLord (Deacon)
on Aug 21, 2001 at 13:06 UTC ( [id://106490]=perlmeditation: print w/replies, xml ) Need Help??

It struck me the other day that I, in my quest to make my code ever shorter (which I understand isn't always a good thing, but that's not the point here), wanted to be able to uc a string automatically with "uc $foo;" as opposed to the longer, more drawn out "$foo = uc $foo;". "Why doesn't it do this already?" I said. "It should just change the variable, like chomp!"

Then I realized that might be a bit troublesome - I don't really want to change my strings with something like "if (uc $foo eq uc $bar)"... and making copies of each would be quite annoying as well. But I still couldn't get over the fact that I didn't like the long version... it just seemed un-Perlish to me.

After a few seconds, I realized something - the statement "uc $foo;" is in void context... nothing's being done with the return value... so why not tinker with uc so that it would recognize the calling context, and if it was void, change the variable?

So, of course, I went and cooked up a quick and dirty module to do this, which is only about 25 lines long and is fairly easily expandable. But the point of all this (this IS a meditation, not me advertising bad code) is that I'm left wondering... is there some reason that I shouldn't be doing this? And why isn't it this way already?

The second question relates a bit more to the title... After all, "lc $foo;" certainly doesn't DWIM now... and I'm wondering if it's unreasonable to expect Perl to work this way. Certainly, I've been known to want crazy things from Perl before... is this an exception, or just more uneducated rambling?

His Royal Cheeziness

Replies are listed 'Best First'.
Re (tilly) 1: DWIM Part Nineteen: Unary Operators in Void Context
by tilly (Archbishop) on Aug 21, 2001 at 16:27 UTC
    One argument for it is that you now have a more customized language to use that you can be more efficient with. Keep trying to do it, and your productivity will rise.

    A big argument against it is that you have just raised the barrier for being able to exchange code with others. For instance if you get used to using this feature, then you may accidentally write and test something that will not work on anyone else's machine.

    Your choice. But I happen to believe the tendancy to not customize local versions of Perl was a major factor in making CPAN be viable. OTOH no less than Damian Conway is a big fan of customized versions of Perl, and will cheerfully customize yours to speak Latin, Morse, and Klingon if given half a chance...

      OTOH no less than Damian Conway is a big fan of customized versions of Perl

      Though, you'll note that I always customize the syntax, never the semantics. And I always do it in such a way that you have to start the customized code with an explicit use Some::Module::Name directive.

      I'm certainly not in favour of customizations that change semantics by stealth.

      As for the original proposal to make built-ins modify their arg in a void context, I know that Larry has considered this and is still working through some of the problems with the idea. Like the fact that the same piece of code inside a sub can be in both void and non-void contexts when called from different points in the code (as others have pointed out in the thread).

      Personally, if we see anything like this, I think it is far more likely that we'll see an explicit syntax for it. There's a strong analogy here to the proposal that operators automatically vectorize when given array arguments. Larry rejected that idea and came up with explicit hyperoperators instead. If he likes the idea of in-place versions of built-ins, I'd expect we'd see some new pseudo-operator to mark them as in-place.

      From that perspective, the extension of $var =~ &whatever to mean $var = whatever $var does have some merit. Though it's still debatable whether it's worth the bother, given you can already so easily write:

      sub apply (&@) { my $func = shift; $_ = $func->($_) foreach @_; } apply {lc} $var; apply {uc} $var1, $var2; apply {abs} @values; # etc.

      Or in Perl 6:

      sub apply (&func, *@args) { $_ = func($_) foreach @args; }

      Or maybe even use an (as yet theoretical) "iterative superposition":

      sub apply (&func, *@args) { each(@args) = func(each @args); }
      I just invented that notion on the spot, but it will definitely go into the next release of Quantum::Superpositions, and I'll also pitch it to Larry (along with any and all) for Perl 6.
        Actually I won't note that.

        I note instead that Quantum::Superpositions manages to achieve semantic effects which are quite different from the usual expectations of Perl programmers. Now while it is true that they are not beyond the range of possibility of the language (as is evidenced by the fact that you achieved them within Perl), I think that they are so far out of the norm for Perl that I see the result as a customization of Perl's semantics.

        But yes, you attempt some forms of sanity, and one of the ways this shows is that you arrange to get an explicit request for insanity before truly opening the floodgates...

Re: DWIM Part Nineteen: Unary Operators in Void Context
by clemburg (Curate) on Aug 21, 2001 at 14:31 UTC

    The second question relates a bit more to the title... After all, "lc $foo;" certainly doesn't DWIM now... and I'm wondering if it's unreasonable to expect Perl to work this way. Certainly, I've been known to want crazy things from Perl before... is this an exception, or just more uneducated rambling?

    In a language like Perl, where you can define your own subroutines and even override the built-in functions (see Camel III, Chapter 11, Overriding Built-in Functions, p. 306), and do that even so that other modules can't detect it, I see really no reason for you to expect that the perl that *all we others* get should do what *you* want.

    Seriously, why don't you just implement the behaviour that you want with your own subroutine (or overridden built-in). Don't expect others to agree to your choices. Make your choices and implement what you need. (If you are really tempted, join the Perl6 effort and try to get your suggestions accepted.)

    To quote Alan Perlis again: "Invent and fit - have fits and reinvent."

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com

      I'm all for customizing your Perl interpreter, either by modules or rearranging the internals. Buuuutt.....

      DOCUMENT WHAT YOU DID

      If you ever expect someone to understand that uc $foo; actually is calling your uc and not the standard one, you have to write that down. And, make sure you write it down somewhere really prominent. Like, at the beginning of all your scripts. Call your module redefining uc something like "Redefinitions::Unary::uc". Make sure it's obvious what you're doing. And, in that module, make sure you explain exactly how you did it, so I can figure it out.

      Or, if you're modifying the interpreter, make sure the shebang line reflects that. Never assume I know more than a really stupid monkey. :)

      ------
      /me wants to be the brightest bulb in the chandelier!

      Vote paco for President!

      Seriously, why don't you just implement the behaviour that you want with your own subroutine (or overridden built-in). Don't expect others to agree to your choices. Make your choices and implement what you need. (If you are really tempted, join the Perl6 effort and try to get your suggestions accepted.)

      One reason for having p5p as an public mailing list is so that suggestions like this can be made there. The other is reason, of course, is because a good bugfix could come from unknown persons.

      I, personally, think the idea has some merit, but I'd be afraid to hurt backwards compatibility (although I can't imagine what current program depends on noop code). I think this would be useful as a module on CPAN, but it would be more useful as a core pragma.

      Without asking the opinions of others and seeing who agrees, it is sometimes difficult to determine how useful other people may find a bit of code. I know I would hate to code and recode the same working piece of software to get it ready for public release, only to find out it wasn't wanted. It's not such a matter of expecting others to agree as asking if others do agree.

      Personally, I think many of Perl's builtins could benefit from such a check. It would probably be a little too slow and too different from what people know to be a default in a future release of 5. IMHO, it's a great candidate for a pragma in 5 or 6, and possibly a good candidate for the default in 6.

      Chris

      Update: Corrected a couple of tpyos.
Re: DWIM Part Nineteen: Unary Operators in Void Context
by Hofmator (Curate) on Aug 21, 2001 at 16:33 UTC

    UPDATE 2: As CheeseLord points out below I was on the right track ... so maybe don't ignore this post completely :) - anyway ++CheeseLord for the interesting idea

    UPDATE: and the problem with me is that I post without testing and thinking properly. Ignore this post, lc is called in void context!! Thanks for making me think straight again dragonchild, I'm the one who's stupid ;-)

    The problem with your suggestion is that it's not always so easy to see what's in void context and what's not. Consider for example this code with your version of lc:

    sub lc_and_chomp { chomp $_[0]; lc $_[0]; # is it in void context??? } my $var = "fOobAR\n"; lc_and_chomp($var); # this alters $var print $var;
    The big problem is that the lc call is now not in void context - although it may look like it at first glance ...

    -- Hofmator

      CheeseLord decides to risk exposing a possible misunderstanding of context issues...

      Actually, you're on the right track. The final line of the function is in void context because the function itself was called in void context. Tweaking your example a bit will show this:

      #!/usr/bin/perl -w use strict; use Void qw( lc ); # My lc sub lc_and_chop(\$) { chop ${$_[0]}; lc ${$_[0]}; } my $foo = 'fUnKy'; lc_and_chop $foo; print "$foo\n";

      Will print "funk". However, if we change the context of the function call...

      - lc_and_chop $foo; + my $bar = lc_and_chop $foo;

      We get "fUnK" printed out. $bar, incidentally, now contains 'funk'. So, you are correct, AFAICT. The solution would be to either switch the calls to lc and chop, or add an extra line returning what we want at the end. I was always in favor of explicit returns, anyway... (Of course, you could always not use my lc, but where would the fun be in that? ;-))

      For those interested (and for those looking for holes in my reasoning), here's what the Void::lc looks like:

      sub lc (\$) { my $ref = shift; my $val = CORE::lc $$ref; return $val if defined wantarray; $$ref = $val; }

      Update: Minor tweak to lc code. (Should do straight copy and paste next time...)

      His Royal Cheeziness

      Ok. I'm stupid. Why isn't the last line of a function in void context?

      ------
      /me wants to be the brightest bulb in the chandelier!

      Vote paco for President!

        /me shouldn't post before caffeine. Please ignore this.

        /\/\averick
        perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

Re: DWIM Part Nineteen: Unary Operators in Void Context
by John M. Dlugosz (Monsignor) on Aug 21, 2001 at 20:59 UTC
    I've run into this issue before, in a C++ class. I want a member foo to act in-place or return a result. What I really want is a succinct way to modify a function, much like + and += are related, as is any @ to its @=.

    So, given x.foo() or foo(x), have a universal way to add the "x=" at the beginning. Maybe x.!foo() can mean "do foo in place on x".

    I'm not proposing actual (good) syntax; just pointing out the idea. What we really want is a succinct "in place" modifier.

    —John

      I have read (in Re: Perl 6 RFCs) that something to this effect was in fact proposed for Perl 6: an extension of the =~ to a general modify-in-place operator. In that case, CheeseLord's problem would reduce to

      $foo =~ lc;
      which is distinctly simpler than the current scenario, but still not as tidy as his proposal.

      On the one hand, I personally kind of like the idea of lc/uc/etc DWCM--on the other, just using the binding operator more generally would probably save all manner of backward-compatibility headaches.

      In any case, I don't think the disposition of that particular RFC is yet known--there doesn't seem to have been a new Apocalypse since May, and I don't see the relevant RFC in the list he took care of in 1 and 2. The feedback on the RFC seems to have been largely positive, but of course it's Larry's opinion that counts in the end.



      If God had meant us to fly, he would *never* have given us the railroads.
          --Michael Flanders

      I think that what you want is called setf() in Common Lisp. Maybe this could give some implementation ideas?

      Christian Lemburg
      Brainbench MVP for Perl
      http://www.brainbench.com

        No, I think setf is just plain assignment. The "place" is not special to the "new value" expression.

        I wonder if the "higher level functions" features in Perl 6 can be used to create this. That would be a good test to see if the proposed feature set is powerful enough.

        —John

Re: DWIM Part Nineteen: Unary Operators in Void Context
by hsmyers (Canon) on Aug 22, 2001 at 00:53 UTC
    Certainly an interesting idea—and not out of keeping with other similar constructs in Perl. But having said that I can't help but think that it isn't really a good idea.

    First of all, say you adapt the void context approach...doesn't that begin to erode the idea of void context? Seems to me that the fuzzier the concept, the less useful. Second thing, since 'Side effects happen!', I'd have to side with the code curmudgeons(tm) and 'just so no!' Don't know about you, but I've more often shot myself in the foot with elegant improvements, than with other method of choice.

    hsm

Re: DWIM Part Nineteen: Unary Operators in Void Context
by damian1301 (Curate) on Aug 21, 2001 at 23:34 UTC
    Good idea. Maybe you could submit it to P6P to come out in Perl 6.

    Do you think that you could possibly create a module so that I may use map in void context as well or can your module do it?

    $_.=($=+(6<<1));print(chr(my$a=$_));$^H=$_+$_;$_=$^H; print chr($_-39); # Easy but its ok.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-16 13:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found