parameter-passing history pass-by-name algol

parameter passing - ¿Qué es "paso por nombre" y cómo funciona exactamente?



parameter-passing history (8)

ALGOL fue diseñado para algoritmos matemáticos. Me gusta la función de suma como un ejemplo de llamada por nombre.

Lo siento, mi ALGOL está un poco oxidada, la sintaxis probablemente no sea la correcta.

.FUNCTION SUM(var,from,to,function) .BEGIN .REAL sum =0; .FOR var = from .TO to .DO sum = function; return sum; .END

Podrías usar suma como

Y = sum(x,1,4,sum(y,3,8,x+y));

En lo anterior, la suma interna (y, 3,8, x + y) generaría una función sin nombre para pasar a la llamada de suma externa. Las variables xey no se pasan por valor sino por nombre. En el caso de las variables llamada por nombre es equivalente a la llamada por referencia de la dirección en C. Se vuelve un poco confuso cuando se trata de recursión.

Borrows hizo máquinas ALGOL. Tenían memoria de palabra de 48 bits con 3 bits de bandera. Los bits de bandera implementaron la cal por nombre de ALGOL. era una máquina de pila, así que cuando la función se cargaba en la pila, la llamada por nombre fag causaría que se llamara. El compilador generaría funciones sin nombre cuando las expresiones se usaran como argumentos. Una variable sería una simple referencia indirecta. Se produciría un error al escribir en una función.

He comprobado la wikipedia y he buscado en Google, pero todavía no puedo entender cómo funciona el paso por nombre en ALGOL 60.


En realidad, llamar por un nombre, no es solo una curiosidad histórica. Puede hacer una llamada por nombre en archivos por lotes de Windows (y una miríada de otros lenguajes de scripting). Saber cómo funciona y cómo utilizarlo de manera efectiva en la programación puede ofrecer soluciones a los problemas. Sé que solo está pasando cadenas para una expansión posterior, pero se puede manipular para que tenga efectos similares a los de llamada por nombre.

call :assign x 1 exit /b :assign setlocal enabledelayedexpansion (endlocal :: Argument 1 is the name of the variable set %1=%2 ) exit /b


Encontré una buena explicación en Pass-By-Name Parameter Passing . Esencialmente, el cuerpo de una función se interpreta en el momento de la llamada después de sustituir textualmente los parámetros reales en el cuerpo de la función. En este sentido, el método de evaluación es similar al de las macros de preprocesador de C.

Al sustituir los parámetros reales en el cuerpo de la función, el cuerpo de la función puede leer y escribir los parámetros dados. En este sentido, el método de evaluación es similar a pasar por referencia. La diferencia es que, dado que con el paso por nombre el parámetro se evalúa dentro de la función, un parámetro como a[i] depende del valor actual de i dentro de la función, en lugar de referirse al valor en a[i] antes la función fue llamada.

La página que he vinculado arriba tiene algunos ejemplos más de donde pass-by-name es útil y peligroso. Las técnicas posibilitadas por el paso por nombre se reemplazan en gran medida hoy por otras técnicas más seguras, como las funciones de paso por referencia y lambda.


Flatlander tiene un ejemplo ilustrativo de cómo funciona en Scala here . Supongamos que quiere implementar mientras :

def mywhile(condition: => Boolean)(body: => Unit): Unit = if (condition) { body mywhile(condition)(body) }

Podemos llamar a esto de la siguiente manera:

var i = 0 mywhile (i < 10) { println(i) i += 1 }

Scala no es Algol 60, pero tal vez arroja algo de luz.


Para aquellos en el futuro:

Concepts in Programming Languages ​​por John C. Mitchell también fue útil.

Pass-by-Name . Quizás la característica más extraña de Algol 60, en retrospectiva, es el uso del paso por nombre. En el paso por nombre, el resultado de una llamada de procedimiento es el mismo que si el parámetro formal fuera sustituido en el cuerpo del procedimiento. Esta regla para definir el resultado de una llamada a procedimiento copiando el procedimiento y sustituyendo los parámetros formales se llama regla de copia Algol 60. Aunque la regla de copia funciona bien para programas puramente funcionales, como lo ilustra la reducción β en el cálculo lambda, la interacción con los efectos secundarios del parámetro formal es un poco extraña. Aquí hay un programa de ejemplo que muestra una técnica conocida como dispositivo de Jensen: pasar una expresión y una variable que contiene a un procedimiento para que el procedimiento pueda usar un parámetro para cambiar la ubicación a la que hace referencia el otro:

begin integer i; integer procedure sum(i, j); integer i, j; comment parameters passed by name; begin integer sm; sm := 0; for i := 1 step 1 until 100 do sm := sm + j; sum := sm end; print(sum(i, i*10 )) end

En este programa, la suma del procedimiento (i, j) suma los valores de j cuando voy de 1 a 100. Si observa el código, se dará cuenta de que el procedimiento no tiene sentido a menos que los cambios causen algún cambio en el valor de j; de lo contrario, el procedimiento solo calcula 100 * j. En la suma de llamadas (i, i * 10) que se muestra aquí, el bucle for en el cuerpo de la suma del procedimiento suma el valor de i * 10 a medida que i va de 1 a 100.


Puede pasar "nombre" en la forma simbólica de una variable que le permite actualizarse y acceder simultáneamente. Como ejemplo, digamos que desea triplicar una variable x que es de tipo int:

start double(x); real x; begin x : = x * 3 end;


Sé que me uniré tarde al club y esto no es necesariamente una respuesta, pero quería agregar una cosa que podría ayudar a aclarar un poco. Siempre he pensado en el Algol pass-by-name como un proceso similar al de las directivas del preprocesador de C ++ (macros, específicamente) reemplaza el nombre de alguna función / variable con el fragmento de código real durante el tiempo de compilación. El nombre de paso reemplaza esencialmente el nombre del parámetro formal con el parámetro real y se ejecuta. Nunca escribí en Algol, pero he oído que pasar por el nombre tendrá el mismo resultado que la referencia de C ++.


Supongo que te refieres a llamar por nombre en ALGOL 60.

Llamada por nombre es similar a llamada por referencia en que puede cambiar el valor del parámetro pasado. Se diferencia de la llamada por referencia en que el parámetro no se evalúa antes de llamar al procedimiento, sino que se evalúa perezosamente. Es decir, se evalúa solo cuando el parámetro se usa realmente.

Por ejemplo, supongamos que tenemos un procedimiento f(x, y) y lo pasamos i e i/2 donde i es inicialmente igual a 10 . Si f establece x a 42 y luego evalúa y , verá el valor 21 (mientras que con la llamada por referencia o la llamada por valor todavía se vería 5 ). Esto se debe a que la expresión i/2 no se evalúa hasta que se evalúe y.

En muchos sentidos, esto parece comportarse como una sustitución literal de texto de los parámetros (con cambio de nombre para evitar conflictos de nombre). En la práctica, sin embargo, esto se implementa utilizando "thunks" (básicamente cierres) para las expresiones pasadas.

El artículo de Wikipedia sobre el dispositivo de Jensen muestra algunos ejemplos interesantes de cómo usar la llamada por nombre. Aqui esta uno de ellos:

real procedure Sum(k, l, u, ak) value l, u; integer k, l, u; real ak; comment k and ak are passed by name; begin real s; s := 0; for k := l step 1 until u do s := s + ak; Sum := s end;

En el procedimiento, la variable de índice k y el término de suma ak se pasan por nombre. La llamada por nombre permite al procedimiento cambiar el valor de la variable de índice durante la ejecución del bucle for. La llamada por nombre también hace que el argumento ak se reevalúe durante cada iteración del bucle. Típicamente, ak dependerá del cambio (efecto secundario) k .

Por ejemplo, el código para calcular la suma de los primeros 100 términos de una matriz real V[] sería:

Sum(i, 1, 100, V[i]).