Call by reference and call by value return (both of which you'd do well to read, if you've not encountered them before) sound remarkably similar. Isn't call by value return just a different (and particularly braindead) implementation of the same semantics that call by reference offers?

Well, no. Call by reference is particularly susceptible to aliasing problems (seemingly different lvalues referring to the same thing), so they can yield different results. For instance, consider this pseudocode (in a completely invented language):

;;; Return X cubed in Y
  Y = X*X
  Y = Y*X
With call by value return, this subroutine might work for all X's and Y's. But with call by reference, they must refer to different lvalues.

Suppose we try to call CUBE(A,A). With call by value return, we first form copies X=A and Y=A, then compute Y=X*X=A*A and Y=Y*X=A*A*A, and only then reassign. So if we first reassign A=X and then A=Y (and the language definition can guarantee a particular order), then we will indeed get the intended effect of cubing A. (If reassignment is performed in the opposite order, nothing happens to A).

With call by reference, the same call raises A to the fourth power! After Y=X*X, A is already squared, so in Y=Y*X both X and Y look at A*A, and Y ends up with A*A*A*A.

With access to external variables, you don't even need dependency on reassignment order to show these effects. For instance, suppose we want to compute quadratic functions of an external variable X:

;;; Return A*X*X+B*X+C in T (X is an external variable)
With call by value return semantics, this subroutine gives the desired behaviour when called as QUADRATIC(A,B,C,X). But with call by reference a wrong result is guaranteed.