Pass-By-Name Implementation
This slide indicates how pass-by-name would be implemented. Here is Jensen's Device again:
begin real procedure sumof(start, stop, index, expr); value start, stop; integer start, stop, index; real expr; begin real sum; sum := 0.0; for index := start step 1 until stop do begin sum := sum + expr end; sumof := sum end; integer i,j; real array arr[1:10]; Sum(1, 10, i, arr[i]); Sum(-20, 20, j, j*j - 4*j + 2); end;

An approximate translation of this into C might look something like this:

double sumof(int start, int stop, int * (*index)(void), double * (*expr)(void)) { double sum = 0.0; for(*index() = start; *index() <= stop; ++(*index())) { sum = sum + *expr(); } return sum; } int i; double arr[10]; int *thunk1(void) { return &i; } double *thunk2(void) { return &arr[i]; } sumof(1, 10, thunk1, thunk2); int j; int *thunk3(void) { return &j; } double *thunk4(void) { static double res; res = j*j - 4*j + 2; return &res; } Sum(-20, 20, thunk3, thunk4);

The name parameters are converted to zero-argument functions which compute the answer. If the expression is a single variable, simple return a pointer to it. For a more complicated expression, compute it, place the result into a temporary, and return a pointer to the temporary. Any variables needed are referenced by the function as a global. These functions are traditionally called thunks.

The function being translated receives a pointer to a thunk for each of its by-name parameters. Its references are translated to call the function and de-reference the returned pointer. If the reference is right-side, the correct value is fetched. Left references where a single variable was sent set the variable, others just discard the value. Since the thunk computes the original expression, it gives the correct value, with the current variable values, each time is is used.

This is all pretty elaborate and expensive. That's why more recent languages don't use it.