Hellow fellow monks, I have responded to 3 or 4 other posts, but this is my first post. So, please be nice, thanks.

I am writing this, because of something I read in Programming Perl. It went something like this: Other languages force you to use a temporary variable to swap variables, but perl doesn't. In perl you can do this: ($a,$b)=($b,$a). I just want you to know, I love the O`Reily series of books, this is not an attack against them, that said, I'll move on.

Now, I'm not exactly sure, but I remember reading somewhere that perl makes an internal copy of the variables to swap. So, that solution is really just ducking the bullet. If you really don't want to use a temporary variable, as in this code:

$temp = $a; $a = $b; $b = $a;
UPDATE: Thanks Rich, I should have changed that last asignment to $b = $temp. Sorry.

You can use a little ingenuity. Now I have never seen any of these following things in a book, nor have I been taught them in a class (I'm only 15, I can't really take many cs classes), so I don't know how widespread this knowledge is. First of all, I don't really recomend you use all of these solutions (only the first is better than using a temporary variable), but it's nice to understand the concepts.

First, if you want to swap integers, use this:

$a ^= $b; $b ^= $a; $a ^= $b;
I benchmarked this, and it performed exactly the same as the temperary solution, but it does not waste a variable. (Those monks who wish to see how this works, just click the readmore at the bottom of this post). If you wish to switch strings without a temporary variable, just use this code:
$a .= $b; $b = substr($a,0,length($a)-length($b)); substr($a,0,length($b)) = '';
When I benchmarked this, the temporary variable solution was very slightly faster. Finally, if your variables could be integers, but could also be floating point numbers, you can use this solution:
$a += $b; $b = $a - $b; $a -= $b;
Now, I know it's easier to just use ($a,$b)=($b,$a), but I wrote this because I was concerned with the language, the book said that other languages force you to use a temporary variable, well they don't. Also, I was recently involved in a robotics competition, in which we used the PBASIC programming language with the BASIC 2SX chip. We had a limited supply of variables, so we had to use solutions like these all the time. So, I'm quite familiar with little optimiztions like this one.
Here is the code:
$a ^= $b; $b ^= $a; $a ^= $b;
It works by creating a mask of $a and $b, and storing it in $a. This mask, when given the original value of $a, returns $b, and vice versa. Next we store in $b, the value of the mask XORed to $b, returning $a, just what we want. Next, we store in $a the value of the mask XORed to $b, which is now the original value of $a, so it returns $b, and the variables are swapped.

The other examples are relatively easy to follow, so I will leave them out of this post.



The 15 year old, freshman programmer,
Stephen Rawls

Replies are listed 'Best First'.
(dws)Re: Temporary Variables
by dws (Chancellor) on May 08, 2001 at 01:58 UTC
    I think there's point being missed. The fact that Perl hides a temporary while doing a   ($b,$a) = ($a,$b); swap isn't important. The salient point is that there isn't a temporary that the programmer has to mentally account for. This is a wetware optimization, not a memory or processor optimization.

    The other ways of swapping might work without a hidden temporary, but all of them contribute more to a programmer's cognitive load than does the simple swap.

    A developer with moderate Perl skills looks at  ($b,$a) = ($a,$b); and thinks "oh, a swap", and moves on. But faced with

    $a ^= $b; $b ^= $a; $a ^= $b;
    the developer has to stop and walk through it. It might look like an XOR swap, but that're still three statements to grok just to make sure. Think of this as a wetware performance hit.

    A big part of the development game is containing cognitive load -- yours and others.

(Ovid) Re: Temporary Variables
by Ovid (Cardinal) on May 08, 2001 at 01:21 UTC

    FYI: Here's an interesting discussion of benchmarking methods of swapping variables.

    You are right that you use a mask or other methods to avoid creating temporary variables. However, those are tricks that are generally used by people coding in lower level languages. I don't think they are "natural" to someone coding in Cobol or BASIC. Good point about "Programming Perl" not being quite accurate, though.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Temporary Variables
by Masem (Monsignor) on May 08, 2001 at 01:21 UTC
    I think that what the book implies is that if the type of $a and $b are of a similar type as a scalar (or untyped), and not necessary a number or string, you have to use a temporary variables to swap as all your methods above use some assumed property of the data type to make the swap "more efficient". I would still think that the ($a,$b)=($b,$a) is going to be near optimal for any data type, and will be the optimal one when the type of $a and $b is not preset or may be different.


    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re (tilly) 1: Temporary Variables
by tilly (Archbishop) on May 08, 2001 at 02:51 UTC
    You can also make a doubly-linked list in C more memory efficient by making your nodes have the xor of the pointer you are coming from or going to. While traversing the list you always know what one of the 2 pointers is, so this allows you to go either way down the list.

    This kind of thing is fun to know about, but more than slightly irrelevant to practical programming these days.

    Besides which, I agree with Programming Perl. Sure, there are lots of special cases where you can not have a temporary at all. But in Perl I notice that you don't handle the case of swapping variables of different types, or variables that are references. In C you may likewise have more fun if you try finding a trick for swapping structs. (There may be one, but if so then I don't know it off-hand.)

    So in general in some languages you need to write a temporary to swap. In Perl you don't write it.

Re: Temporary Variables
by virtualsue (Vicar) on May 08, 2001 at 02:17 UTC
    "Other languages force you to use a temporary variable to swap variables, but perl doesn't. In perl you can do this: ($a,$b)=($b,$a)." srawls points out that TIMTOWTDI

    Yes, it is absolutely true that it is possible to use XOR in order to swap the values of two variables without the use of a temporary variable*. This fact is fairly well-known, and I'd be very surprised of the authors of Programming Perl didn't know about it. I assume that they were just trying to highlight the fact that Perl provides an easy and obvious way to swap the values of 2 variables. Perl is a higher-level language, which means that it provides a higher-level of abstraction. For a number of reasons, higher-level language programmers don't usually want to use 3 rather obscure-appearing statements when they could use one quite obvious self-documenting one to directly accomplish the same thing. It is the job of the interpreter to substitute optimal lower-level code for these powerful, tidy constructions.


    *Not every language provides XOR so the statement in the book isn't entirely incorrect. Putting a "Some" in front of that sentence gets them right off the hook entirely, assuming that it isn't there already - I haven't got the time to try to find it.
Re: Temporary Variables
by rchiav (Deacon) on May 08, 2001 at 18:00 UTC
    Just as an FYI - you might want to change..
    $temp = $a; $a = $b; $b = $a;
    to what you really meant.

    Rich