Ci sono due possibili implementazioni. La prima è la sostituzione testuale, I.e. la funzione chiamata viene espansa in linea con i riferimenti ai suoi parametri sostituiti con il codice che si fornisce. Questa è fondamentalmente una forma di macro e soffre di molti dei problemi inerenti a questo, in particolare che una funzione non può essere resa ricorsiva quando definita in questo modo.
L'altro è usare un paio di "thunk", cioè. codice generato che sostituisce le operazioni di lettura e scrittura del parametro. Puoi simularlo in un linguaggio OOP definendo un'interfaccia, ad es.
public interface CallByNameArg<T>
{
void set (T value);
T get();
}
Quindi una funzione usa quei metodi quando vuole accedere ai suoi argomenti, ad es. una funzione in una lingua chiamata per nome simile alla seguente:
int sum (int index, int start, int end, int value) // call-by-name
{
int r = 0;
for (index = start; index < end; index ++) r += value;
return r;
}
diventa
int sum (CallByName<int> index, CallByName<int> start, CallByName<int> end, CallByName<int> value)
{
int r = 0;
for (index.set (start.get ()); index.get() < end.get();
index.set (index.get () + 1))
r += value.get();
return r;
}
e un sito di chiamata:
int a[] = ....;
int i;
int s = sum(i, 0, a.length; a[i]);
diventa (assumendo una lingua con le giuste chiusure, quindi non Java anche se ho usato la sintassi simile a Java):
int s = sum (new CallByNameArg {
void set (int value) { i = value; }
int get () { return i; } }, new CallByNameArg {
void set (int value) { throw NotModifiable; }
int get () { return 0; } } new CallByNameArg {
void set (int value) { throw NotModifiable; }
int get () { return a.length; } }, new CallByNameArg {
void set (int value) { a[i] = value; }
int get () { return a[i]; } });
Se non hai chiusure effettive nella tua lingua, puoi simularle spostando variabili modificabili (in questo caso i e a) in un oggetto e definendo le istanze CallByNameArg come classi interne o simili.
Spero che ciò lo renda un po 'più chiaro.