Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Squeezing $a+1 to be magical like $a++

by coolmichael (Deacon)
on Oct 10, 2001 at 10:01 UTC ( #117939=perlquestion: print w/replies, xml ) Need Help??
coolmichael has asked for the wisdom of the Perl Monks concerning the following question:

So, perlop says that $a++ is magical. I like it's magic, and it would be fantastically convienent if there was a way to make $a+1 magical. I've been banging my head on my desk trying to figure this one out. I've included what I tried to do (except for some of the regex disasters), but I'm sure there must be a better way.

#$a=(--(($a++)++)); #ugly, and doesn't compile sub mag1{ #works, but still not pretty. $b=shift; ++$b; } $a = "07"; $a++; print "should be 08: $a\n"; $a = $a + 1; print "should be 09: $a\n"; #####OUTPUT should be 08: 08 should be 09: 9

Replies are listed 'Best First'.
Re: Squeezing $a+1 to be magical like $a++
by jeroenes (Priest) on Oct 10, 2001 at 14:16 UTC
    There is Yet Another Reason why you really don't want to magicalize the adding operator, and that is the way it handles alphanumeric characters. E.g., 'z9' with ++ becomes 'aa0'. What would you want to do with 'z9' + 'a04'? That promises to get unbelievable messy. And we even haven't touched the subject of fractions... I suggest you leave the magic alone and use sprintf instead.
    sub format_add{ my ($x, $y) = @_; my $ret = $x + $y; my $digs = length $x; sprintf("%0${digs}d", $ret ); }
    Of course you can overload the '+' with this sub.

    The ++ can do some strange things, by the way:
    $a=0.5; print ++$a; #prints 1.5 $a='a0.5'; print ++$a; #prints a6 #(so ++ ignores the dot and squashes the 0) $a='2a'; print ++$a; #prints 3 #(because 2a in numeric context returns 2)

    Apparently it is a beast to handle with care.

    "We are not alone"(FZ)

Re: Squeezing $a+1 to be magical like $a++
by Zaxo (Archbishop) on Oct 10, 2001 at 10:20 UTC

    Not that I approve of this, but you would need to overload binary + to recognise when it is called in void context. Otherwise my $y = $x + 1; would modify $x with chaos resulting. I don't think there is a way to do that in the manner of wantarray.

    As an aside, $a and $b are already magical, representing package scope variables sacred to sort. Also be careful of numbers with leading zeros. They can be taken as octal and refuse to recognise '8' and '9'

    Update: Rereading your question, I think I misunderstood what you want. Here is code without any overloading:

    sub addsome { ++$_[0] for 1..$_[1]; }
    This is rough and completely untested. The references to args are used so that the original string is modified with ++ magic.

    Update2: The code works, but it's not very efficient. Now I understand that you want addition to act on alphanumeric strings according to the rules for ++ on non-numeric strings. I suspect you don't require modification in place. That makes my comment about void context useless, and suggests that overload of binary + is perfectly approporiate.

    After Compline,

      Not that I approve of this, but you would need to overload binary + to recognise when it is called in void context. Otherwise my $y = $x + 1; would modify $x with chaos resulting. I don't think there is a way to do that in the manner of wantarray

      When you write a method that overrides a binary operation (like add), the method gets passed three arguments - the two operands and a third argument which tells you if the operands have been swapped (for code like 1 + $obj). If this third argument is undef then the original statement is in void context.

      Blessed Be
      The Pixel

        Since that third argument is ... ah, erm... overloaded, is it possible to tell the difference between 1 - $obj and $obj - 1 if they are both in void context? Will the third param be undef even if the arguments have been swapped?


Re: Squeezing $a+1 to be magical like $a++
by blakem (Monsignor) on Oct 10, 2001 at 10:46 UTC
    I'm not too familiar with overloading, so this is a "wonder if I can get that to work" snippet instead of a "I'd recommend doing it this way" suggestion.

    Perhaps someone more familiar with overloading can point out the shortcomings of this quick hack. (other than not working for negative numbers, and the really poor algorithm of repeating $x++ 10 times for $x + 10)

    #!/usr/bin/perl -wT use strict; package MagicalPlus; use overload '""' => sub { ${$_[0]} }, '+' => \&myadd, 'fallback' => 1; sub myadd { my $first = ${$_[0]}; my $second = $_[1]; $first++ while($second-->0); return addmagic($first); } sub addmagic { my $string = "".shift; my $self = \$string; bless($self, __PACKAGE__); } package main; my $x = MagicalPlus::addmagic "006"; # create our magic var for (1..10) { # watch it works its magic print "$x + $_ = "; $x = $x + $_; # magical? print "$x\n"; } =OUTPUT 006 + 1 = 007 007 + 2 = 009 009 + 3 = 012 012 + 4 = 016 016 + 5 = 021 021 + 6 = 027 027 + 7 = 034 034 + 8 = 042 042 + 9 = 051 051 + 10 = 061


Re: Squeezing $a+1 to be magical like $a++
by htoug (Deacon) on Oct 10, 2001 at 12:40 UTC
    I just can't fathom why you want $a=$a+1 to work just like $a++. Why not just use the latter?

    $a+1 is a very useful idiom to ensure that the value is numeric, while $a++ is magic.

    Please explain what you want it for.

Re: Squeezing $a+1 to be magical like $a++
by jryan (Vicar) on Oct 10, 2001 at 10:53 UTC
    It sounds like you just want to be able to add some sort of constant to your a string. You can't really do that; however, here is a function that will give you want you want:

    sub magic { my ($v, $i) = @_; $v=substr($v,0,length($v)-1).chr(ord(substr($v,-1))+$i); } print magic('a', 1), ", "; print magic('c', -1), ", "; print magic('meep', 2); # will print "c, a, meer"

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://117939]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (1)
As of 2018-05-27 23:54 GMT
Find Nodes?
    Voting Booth?