2009-03-19 12 views
9

Estoy escribiendo un intérprete de Scheme, y en el caso de una sentencia if, tales como:¿No puede devolver nada de una función en Scheme?

(if (< 1 0) 'true) 

Cualquier intérprete He intentado sólo devuelve un nuevo símbolo. Pero cuando codifiqué esto, tenía un si para si había una expresión alternativa. ¿Qué puedo devolver en el si tal que nada se imprima?

(if (has-alternative if-expr) 
    (eval (alternative if-expr)) 
    #f) ;; what do I return here? 

Respuesta

10

Según la R6RS specification:

Si < de prueba> rendimientos #f y no < alternativo> se especifica, entonces el resultado de la expresión no está especificado.

¡Así que vuelve loco, devuelve lo que quieras! Aunque #f o '() son lo que yo personalmente esperaría.

+1

Lo mismo es cierto también en R5RS. –

+1

Prefiero #f ya que (si '() ...) dará la rama #t (¿tiene que probar con nulo?). – Jyaan

1

En primer lugar, que está bien si requiere tener una cláusula else, si se hace que sea más fácil para usted. En segundo lugar, Scheme admite devolver múltiples valores de una función, por lo que si implementara los valores de retorno como una lista, podría tener una lista vacía que indique que no se proporcionó ningún valor de retorno.

(if (has-alternative if-expr) 
    (eval (alternative if-expr)) ; make sure eval returns a list 
    '()) 

Una distinción importante aquí: No devolveré una lista vacía si no hubiera otra cláusula. La lista vacía significa que no hubo un valor de retorno. Si hubiera un valor de retorno de una expresión (digamos que era 3), usted tendría (3) como el retorno de la evaluación detrás de las escenas. Del mismo modo, devolver varios valores de una expresión haría que la lista de resultados eval tuviera múltiples elementos.

Finalmente, en realidad, podría devolver cualquier cosa si la condición falla y no hay más, porque sería un error en un programa intentar capturar el valor de una función que no devuelve nada . Como tal, sería el trabajo del programador, no el idioma, detectar este error.

0

Lo que es malo con sólo:

(if (has-alternative if-expr) (eval (alternative if-expr))) 

?

+0

¿Así que esto se predetermina a lo que sea que haga el lenguaje del intérprete de esquemas? No hay nada de malo, a menos que intente implementar un Esquema compatible con R6RS además de un Esquema que no es compatible con R6RS :-P –

2

Ciertos esquemas (PLT, Ikarus, Chicken) tienen un tipo void, que usted puede producir con (void).

En PLT al menos, vacío es lo que obtienes cuando lo haces (cuando (< 1 0) #t).

(v4 PLT no permite si sin una cláusula else.)

8

Esquema de hecho puede volver no hay valores:

> (values) 

En R5RS la forma de un solo brazo de si se especifica para devolver un valor no especificado. Eso significa que depende de usted decidir qué valor devolver. Bastantes pocos esquemas han elegido introducir un valor específico llamado "el valor no especificado" y devuelve ese valor. Otros devuelven "el valor invisible" # < void> y el REPL se escribe de modo que no se imprima.

> (void) 

En un principio se podría pensar, esto es lo mismo que (valores), pero tenga en cuenta la diferencia:

> (length (list (void))) 
    1 

    > (length (list (values))) 
    error> context expected 1 value, received 0 values 
    (Here (list ...) expected 1 value, but received nothing) 

Si # < vacío> es parte de una lista, se imprime:

> (list (void)) 
    (#<void>) 
2

Cuando el valor de retorno no está especificado, puede devolver lo que quiera; el usuario simplemente no puede confiar en que ese valor esté ahí, nunca, o en todas las implementaciones.

1

La gente extraña devolvería 'nil o '|| (el símbolo vacío). El problema es devolver un símbolo que no se puede devolver por (eval (alternative if-expr)) para evitar confusiones.

Si algo puede ser devuelto por (eval (alternative if-expr)) y todavía quieren saber si llegó o no en esta alternativa, usted tiene que empacar el resultado con más información:

(if (has-alternative if-expr) 
    (cons #t (eval (alternative if-expr))) 
    (cons #f #f)) 

Por lo tanto, el resultado es una cons celda. Si su auto es #t, entonces evadiste algo. Si es #f, no lo hiciste.

Cuestiones relacionadas