Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!cmcl2!seismo!columbia!caip!brl-adm!brl-smoke!smoke!chris@maryland.ARPA From: chris@maryland.ARPA (Chris Torek) Newsgroups: net.lang.c Subject: Re: Swap by name Message-ID: <1955@brl-smoke.ARPA> Date: Thu, 3-Jul-86 22:12:00 EDT Article-I.D.: brl-smok.1955 Posted: Thu Jul 3 22:12:00 1986 Date-Received: Sat, 5-Jul-86 06:11:48 EDT Sender: news@brl-smoke.ARPA Lines: 106 From: Root Boy Jim I seem to remember three types (possibly four) of parameter passing: 1) Call by value C scalars 2) Call by reference C pointers, arrays, Fortran variables 3) Call by name Algol call by name (it also does val & ref) The fourth method (as you mention later) is call by value-result. Call by reference went something like this: the calling routine would pass the string representation of the argument and the caller would parse it to figure out the argument. This much work is not necessary. You simply build static links or a display and use conventional non-local references in the thunk procedures. Each thunk procedure returns a pointer to the variable that represents the evaluation of the appropriate argument, as performed in the context of the caller. (If a compiler-generated thunk requires a temporary variable---all expression-thunks do---that temporary is unnamed, so the fact that a Pascal-ish thunk would be nested one level greater than the caller is irrelevant. To put it another way, a compiler can do whatever it wants. :-) ) From: Doug Gwyn (VLD/VMB) [Giving equal time to UUCP domains . . . :-)] No, you just implemented an elaborate form of "call by reference". I merely chose a poor example. Call by reference and call by name often have identical effects. See my followup for a better example. (Incidentally, my expression `example', contained in a comment, has a different problem: it returns the address of a stack variable that is no longer active by the time the caller uses it. `t' should have been declared `static'. This is what comes of dashing off an article just before bed . . . .) It is possible to implement full call by name in C, but it is difficult, for nonlocal reference is difficult; and no one ever used call by name after Algol anyway---most likely because everyone thinks it is terrible. Nonlocal reference *is* possible, but probably best left to a compiler. Kludges are not too hard to write, but are error-prone: the programmer must keep track of the lexical level of each routine, and know how many levels up to look, and at what offset, for each nonlocal variable. The other three of Root Boy's methods of parameter passing are also available to C programmers. Call by value is of course trivial. Call by reference is easy to achieve using pointers (though in fact the call is still `by value': the value of the pointer expression). Call by value-result is also easy enough in C, though as with call by reference, it requires cooperation of both caller and callee: /* Call by value-result */ f() { int i, j; i = 1; j = 2; call_by_value_result(&i, &j); } call_by_value_result(addr1, addr2) int *addr1, *addr2; { /* perform the entry protocol: obtain the arguments */ int arg1 = *addr1, arg2 = *addr2; /* * code dealing with `arg1' and `arg2' as though * those were the arguments; no `return's; then: */ /* perform the exit protocol: modify the arguments */ *addr1 = arg1; *addr2 = arg2; } The entry protocol is the `value' part; the exit protocol supplies the `result'. Incidentally, call by value-result is a legal implementation in at least one of the many FORTRAN standards. It tends to surprise those who alias a variable and depend on call by reference to modify two parameters at once: PROGRAM CALLBY INTEGER ARG C Translate the following two PRINTs as appropriate for whatever C compiler restrictions you have. PRINT *, ' If it says "3 3" then "7 7", you have call by reference;' PRINT *, ' if it says "3 3" then "7 3", you have call by value-result.' ARG = 3 CALL TESTIT (ARG, ARG) C N.B.: If value-result, ARG could be either 3 or 7 now! STOP END SUBROUTINE TESTIT (I, J) INTEGER I, J PRINT *, I, J I = 7 PRINT *, I, J RETURN END