11/21/2009

What Is a Call By Reference / Pass By Reference?

What's the difference between passing values and references to a function?

Brief answer: Passing a variable by value sends a copy of the value to the function, so the original value cannot be changed by what happens inside the function. Passing by reference tells the function where the value of the variable is stored in memory, so whenever the variable is changed inside the function, it is changed for the main program too after the function is complete. Some languages like C++ and PHP can do this with variables. Others like Javascript cannot use references with variables, but can do it by passing objects.
 

Calling? Passing? Say what?!


If you've done some basic programming with a modern language, you've likely used functions to organize and modularize your code. With functions, a programmer can take a long list of main programming instructions, break it up into chunks, and then rewrite the main instructions to be a much shorter, and easier to understand set of instructions.
userInput = getUserInput();
processedInput = getProcessedInput(userInput);
displayOutput(processedInput);
These three lines all make calls to different functions. Calling a function means, you request a function to do something for you -- also known as invoking a function. The first one does not send any value, but it does receive a value. The second one does send a value, and it does receive a value, too. The last one sends a value, but it does not need to receive any value back. When you send data or value to a function, you are passing a value These second and third lines are call-by-value requests.


In the real world...


Put all the program lingo to the side for a moment.
Imagine you had the balance of your bank account written on a little piece of paper (Note says $12,000). You ask your partner or spouse to figure out how much is left after you pay the bills this month. He/she says, "Well, I need to know how much is in your account, then."

You can do one of two things: 1) hand your spouse your piece of paper, or 2) copy the balance onto another piece of paper and hand the copy to your spouse.

He/she takes the paper, gets all the bills together, disappears to do the calculations and comes back after a while. They hand you back a piece of paper with a new value ($8,500).

If you had given your spouse a copy of the value, you'd now have two pieces of paper (Note says $12,000 and Copy says $8,500). But if you had given them your one piece of paper, and did all their calculations, erased everything on that little piece of paper, and wrote down the new value, you would have one piece of paper with the new value (Note says $8,500) and no longer know what the original value was.

Either one of these situations could be fine, it depends on what you wanted back.


Pick Your Poison


There are two ways that the main program can get information back from the functions.
  • Call-By-Value - Send a request with a copy of a variable's value, return a single new value or array. (ex. Note and Copy)
  • Call-By-Reference - Send a request with a reference to the value of the array, change the variable value inside the function.  (ex. Note only)


Simple for Simon


Here's the simplest example I can think of. You have a number, and you want to double it, so you send the number to a function that multiplies it by two.

Here's a call-by-value example written in PHP:
$origNumber = 7;
$newNumber = doubleIt($origNumber);

function doubleIt($numberSent) {
   $doubledNumber = $numberSent * 2;
   return $doubledNumber;
}

So, in the example above, a copy of the original value (7) is passed to the function called doubleIt(). That value is received by the function. The value is multiplied times 2 to get a new value (14). Then that value is RETURNED back to the main program. The original value remains the same (original = 7, returned value = 14).

Here's the call-by-reference version:
$origNumber = 7;
$newNumber = doubleIt($origNumber);

function doubleIt(&$numberSent) {
   $numberSent = $numberSent * 2;
   return;
}

In this example, nothing is returned, but instead, the value sent for the variable itself is CHANGED.

The first part is the same, the original value (7) is passed to the function. But, in this case, the function receives a reference, not a copy of the value. Look at the heads of the functions. The only difference between the coding is the ampersand next to the variable name where data is being received. The program directly changes the value of the variable (original value = 14) that is sent to it in this call-by-reference.


Explaining by Example


Let's say we have a situation where we have a person's Social Security Number. And we want to get their last name. We could do something like this using a call-by-value (note: not working code, just a hypothetical example):
Example 1. (Call-by-Value with single value returned)

$lastName = getLastNameUsingSSN($customerSSN);
echo $lastName;

function getLastNameUsingSSN($ssnSent) {
   $sql = "SELECT lastName FROM customers WHERE ssn = $ssnSent LIMIT 1";
   [... some magic code that retrieves the last name from a database ...]
   $lastName = $dbResult["lastName"];
   return ($lastName);
}
Okay, great! We send a SSN number (123-45-6789), and the function returns a last name from the customer database (Jones).

What if we want more than the last name, we could theoretically do something like this:
Example 2. (Call-by-Value with array returned)

$customerData = getCustomerInfoArrayUsingSSN($customerSSN);
echo "Name: $customerData[1] $customerData[0]\n";
echo "Phone: $customerData[3]\n";
echo "Email: $customerData[2]\n";

function getCustomerInfoArrayUsingSSN($ssnSent) {
   $sql = "SELECT * FROM customers WHERE ssn = $ssnSent LIMIT 1";
   [... some magic code that retrieves the last name from a database ...]
   $customerInfoArray[0]= $dbResult["lastName"];
   $customerInfoArray[1]= $dbResult["firstName"];
   $customerInfoArray[2]= $dbResult["email"];
   $customerInfoArray[3]= $dbResult["phone"];
   return ($customerInfoArray);
}
 Well then, we are doing the same thing, except we are asking for an array of data to be returned instead of a single value. Depending on the language, this it can get confusing, if it's allowed at all. If you can use a name-value array, it is a little easier to work with named indexes, rather than trying to work with numbered indexes. "lastName" is easier to understand than "0";

But it's still easy to get mixed up like that.

One way to avoid confusion is to use a call-by-reference.
Example 3. (Call-by-Reference with multiple values being changed)

getCustomerInfoArrayUsingSSN($customerSSN, $fName, $lName, $phone, $email);
echo "Name: $fName $lName\n";
echo "Phone: $phone\n";
echo "Email: $email\n";

function getCustomerInfoArrayUsingSSN($ssnSent, &$fName, &$lName, &$phone, &$email) {
   $sql = "SELECT * FROM customers WHERE ssn = $ssnSent LIMIT 1";
   [... some magic code that retrieves the last name from a database ...]
   $lName= $dbResult["lastName"];
   $fName= $dbResult["firstName"];
   $email= $dbResult["email"];
   $phone= $dbResult["phone"];
   return;
}
If you can understand this, you'll see that calling by reference results in a more direct manipulation of the values in the main program.  Nothing is returned from the function. The values stored for the variables used in the main program and changed by the procedures in the function.

Yes, you can return something, too, if you like (a status confirmation for example).

Yes, this can mess up things pretty badly if it's done wrong.


PHP Usage

PHP allows this method pretty easily. In the function head, you just put an ampersand next to the variable you want to use as a reference:
PHP Example (using colors of traffic light)

$color = "green";
$meaning = "";

if (trafficLight($color, $meaning)) {
   echo "$color $meaning\n";
}
else {
   echo "I don't understand the color $color";
}
exit();

function trafficLight ($colorSent, &$meaningOfLight) {
   if ($colorSent == "red") {
       $meaningOfLight = " means stop";
       return TRUE;
   }
   elseif ($colorSent == "green") {
       $meaningOfLight = " means go";
       return TRUE;
   }
   return FALSE;
}

Here, the value of $meaning is changed, and a boolean value is returned from the function. In this case the output would be "green means go" because a value of "TRUE" was returned to the if function. If the color was changed to "red" the output would be "red means stop" because "TRUE" again would be returned. If the color were changed to "blue", a value of "FALSE" would be returned to the if statement that called the function, and the output would be "I don't understand the color blue".


Javascript Usage

Only Javascript objects can be passed by reference.

Primitives or simple variables can only be passed by value.

No comments :

Post a Comment