3
$\begingroup$

I have searched on Google, but I can't quite understand what is pass-by-value-result. What is the advantage and disadvantage of using pass-by-value-result?

If I have a program code like this, what will be the result when parameters are passed by value-result?

#include <stdio.h>

int a=2;
int b=1;

void fun(int x, int y) {
    b=x+y;
    x=a+y;
    y=b+x;
}

void main() {
    fun(b,b);
    printf("%d %d\n",a,b);
}
$\endgroup$
1
10
$\begingroup$

Note: parameter passing by xxx is sometimes called "pass by xxx" and sometimes "call by xxx". I will use both expressions indifferently.

Parameter passing by value-result consists in passing by value when the subprogram (whatever it is) is called, and then, when it terminates, assign the current value of the formal parameter in the subprogram back to the actual parameter if it is a mutable entity, such as a variable or an array entry. Of course, no such assignment may occur if the actual parameter is a non mutable value providing entity such as an expression, a function call, a constant (though some old versions of Fortran have been known to assign values to constants, so that printing 3 could actually print 5).

Afaik, fortran was first to use this mechanism (I do not know for Cobol). It is also available in Ada. Actually, Ada has call by value (IN parameter) and call by result (OUT parameter). OUT parameters are not initialized at call, but assign current value of formal parameter to the actual parameter upon return. Parameter passing by value-result (IN OUT) is the combination of both. Actually, the case of Ada is more complicated (at least in its initial versions) because it was explicitly allowed to implement these parameter passing mechanism with a call by reference. I am not sure of the current status of the language. This of course muddles the discussion below.

Comparing parameters passing mechanisms is dependent on the language considered.

Issues you may want to consider are cost in time or space, readability and maintenance, compiling issues such as efficiency and optimization, and also semantics such as determinacy of programs, and also programming convenience. (I may have forgotten some).

Many of these issue are stongly impacted by aliasing phenomena. Whenever the same mutable entity (possibly a simple variable) can be accessed in different ways, it becomes harder to analyse the program, determine what parts of the computation may interfere with other parts. When there are several threads of computation, this may cause race conditions making the computation dependent on timing. When compiling program, aliasing may make it harder to get a reliable definition-use relation for performing some otpimizations.

Hence,I would consider aliasing problems a major issue when comparing computing mechanisms.

Since you need ways to communicate in programs, assessing a parameter passing mechanism can only by comparing to alternatives.

Regarding pass-by-value-result, the are only two that I see:

  • Doing nothing on exit.
    Then you can pass information back to the caller only as function result, or by assigning a global variable visible from both callee and caller.

  • Using pass by reference.
    Then the formal parameter becomes just another name, an alias, for the actual parameter, so that the actual parameter has the value of the formal one upon exit (as well as before exit).

Issues

Time and space cost

One advantage of call by reference over call by value-result is that it is often cheaper, especially if the data to be passed is large (time/space costs of copying). Call by reference may have a time cost because of indirect addressing, though that can sometimes be optimized out.

Aliasing

The major drawback of call by reference is all I said about aliasing. So that may be considered a very good point for pass-by-value-result.

Side effects and evaluation order

Then call by value-return has a problem when returning the values, as in your example. If two formal parameters (x and y in the example) actually get the same actual parameter (b in the example) then the actual parameter will take on return a value that depends on the order chosen for returning values. Hence, it is essential to define it. In any case, such a situation is a sure indicator of bad programming practice.

This problem does not exists with call by reference. But call by reference is a completely different kind of computation, as shown by executing your example in call by reference.

Returning values is a side-effect on the actual parameters. Computations with side-effects always raise issues of order dependence. If the evaluation of actuall parameters entails some side-effects (for example by calling a function with side-effects), then the order of evaluation of arguments may have an impact on the computation. That is why side-effect are to be avoided, or at least carefully managed.

Objects identity

If you have a language that allows to distinguish identity and egality, the call by reference wil preserve identity, while call by value will not. For example, when you copy an integer (for example by assignment), there is no way you can distinguish the new copy from the old one. But Object-Oriented (OO) languages could let you make a difference, and have a test for equality (same value) and a test for identity (same reference).

Well definedness of call by value (irrespective of result)

Another problem is that call by value may not be well defined. You have to determine what a value is. How deep do you copy an object implemented with references (pointers) when doing call by value. When a reference is not followed for copying, it is an open door for aliasing problems.

I am not saying these issues are untractable, but only that you have to deal with them consistently throughout the language (consistency with assigment in particular). And that does not make for a clearcut answer, independently of the rest of the language, and the style of programming it supports.

Running the example in call by value-result and call by reference

Notation

    a<==b  a becomes aliased to b
    a==b   a is alias of b  (reminder)
    a<-3   a is assigned the value 3

Call by value-result:

    Call of fun(b,b): x<-1 y<-1 b<-2 x<-3 y<-5 return print 2 (3 or 5)   

unpon returning, b ends up with 3 or 5 depending on the order of argument return.

Call by reference:

    Call of fun(b,b) x<==b y<==b b==b<-2 b==x<-4 b==y<-8 return print 2 8
$\endgroup$
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.