2009-12-08 5 views
6

Estoy tratando de dar sentido al código de ejemplo here (a continuación Ejemplos). No entiendo que parametrice constructo. Los documentos para él son here, pero no ayudan. ¿Qué hace?¿Qué hace 'parametrize' en DrScheme?

+0

¿Por qué utilizar tinyurl.com? No hay restricciones de espacio significativas con solo usar la url completa, y el abreviador hace que el enlace parezca más sospechoso. –

+1

El enlace tiene paréntesis al final que hace que no funcionen con el marcado que SO usa – Claudiu

+0

Jiminy Christmas, esos enlaces ni siquiera funcionarán con el estilo de marcado de citas en el fondo. – Chuck

Respuesta

13

parameterize se utiliza para tener valores que tienen un "alcance dinámico". Obtiene un parámetro con make-parameter. El parámetro en sí mismo se comporta como una función: llámalo sin entradas y obtienes su valor, llámalo con un valor y establecerá el valor. Por ejemplo:

> (define p (make-parameter "blah")) 
> (p) 
"blah" 
> (p "meh") 
> (p) 
"meh" 

Muchas funciones (incluidas muchas primitivas) usan parámetros como una manera de personalizar su comportamiento. Por ejemplo, printf imprimirá cosas usando el puerto que es el valor del parámetro current-output-port. Ahora, decir que tiene alguna función que imprime algo:

> (define (foo x) (printf "the value of x is ~s\n")) 

Por lo general llama a esta función y ver algo impreso en la pantalla - pero en algunos casos se desea utilizar para imprimir algo en un archivo o lo que sea . Usted puede hacer esto:

(define (bar) 
    (let ([old-stdout (current-output-port)]) 
    (current-output-port my-own-port) 
    (foo some-value) 
    (current-output-port old-stdout))) 

Un problema con esto es que es tedioso para hacer - pero eso es fácil de resolver con una macro. (De hecho, PLT todavía tiene una construcción que lo hace en algunos idiomas: fluid-let). Pero aquí hay más problemas: ¿qué ocurre si la llamada al foo produce un error de tiempo de ejecución? Esto puede dejar el sistema en mal estado, donde todos los resultados van a su puerto (y ni siquiera verá un problema, ya que no imprimirá nada). Una solución para eso (que también se usa en fluid-let) es proteger el guardado/restauración del parámetro con dynamic-wind, lo que garantiza que si hay un error (y más, si conoce continuidades), entonces el valor aún se restaura.

Entonces, la pregunta es ¿cuál es el punto de tener parámetros en lugar de simplemente usar globales y fluid-let? Hay dos problemas más que no puedes resolver con solo globales. Una es lo que sucede cuando tienes múltiples hilos, en este caso, establecer el valor temporalmente afectará a otros hilos, que aún pueden querer imprimir al resultado estándar. Los parámetros resuelven esto teniendo un valor específico por subproceso. Lo que sucede es que cada hilo "hereda" el valor del hilo que lo creó, y los cambios en un hilo son visibles solo en ese hilo.

El otro problema es más sutil.Decir que usted tiene un parámetro con un valor numérico, y que desea hacer lo siguiente:

(define (foo) 
    (parameterize ([p ...whatever...]) 
    (foo))) 

En el esquema, "cola de llamadas" son importantes - que son la herramienta básica para la creación de bucles y mucho más. parameterize hace algo de magia que le permite cambiar el valor del parámetro temporalmente, pero aún conserva estas llamadas de cola. Por ejemplo, en el caso anterior, obtendrá obtener un bucle infinito, en lugar de obtener un error de desbordamiento de pila: lo que sucede es que cada una de estas expresiones parameterize puede detectar de alguna manera cuando hay una anterior parameterize que ya no necesita hacer su limpiar.

Por último, parameterize realmente utiliza dos partes importantes de PLT para hacer su trabajo: utiliza celdas de hilo para implementar valores por subproceso, y utiliza marcas de continuación para poder conservar las llamadas finales. Cada una de estas características es útil en sí misma.

+0

respuesta impresionante - ¡gracias! – Claudiu

3

parameterize establece los parámetros particulares a los valores especificados para la duración del bloque, sin afectar sus valores fuera de él.

+0

hmmm interesante – Claudiu

3

Parametrizar es un medio por el cual puede vincular dinámicamente valores dentro de una función existente, sin usar lambda para hacerlo. En la práctica, a veces es mucho más fácil usar parametrizar para volver a enlazar valores dentro de una función en lugar de tener que pasar argumentos y vincularlos usando lambda.

Por ejemplo, supongamos que una biblioteca que utiliza emite HTML a stdout pero, por comodidad, desea capturar ese valor en una cadena y realizar más operaciones en ella. El diseñador de la biblioteca tiene al menos dos opciones para facilitarle: 1) aceptar un puerto de salida como argumento para la función o 2) parametrizar el valor del puerto de salida actual. 1 es feo y una molestia. 2 es más agradable ya que el comportamiento más probable es imprimir a stdout, pero en caso de que desee imprimir en un puerto de cadena, puede simplemente parametrizar la llamada a esa función.