2009-03-19 25 views
9

Sto scrivendo un interprete schema, e nel caso di un'istruzione if come ad esempio:Non si può restituire nulla da una funzione in Scheme?

(if (< 1 0) 'true) 

Qualsiasi interprete Ho provato solo restituisce un nuovo prompt. Ma quando ho codificato questo, ho avuto un se per se ci fosse un'espressione alternativa. Cosa posso restituire nel caso in cui non venga stampato nulla?

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

risposta

10

Secondo il R6RS specification:

Se < prova> rese #f e nessun < alternate> è specificato, allora il risultato dell'espressione non è specificato.

Quindi impazzisci, restituisci tutto quello che vuoi! Sebbene #f o '() siano ciò che personalmente mi aspetterei.

+1

Lo stesso vale anche per R5RS. –

+1

Preferisco #f poiché (se '() ...) forniremo il ramo #t (devi testare con null?). – Jyaan

1

Per prima cosa, è necessario richiedere se avere una clausola else, se è più semplice per te. In secondo luogo, Scheme supporta la restituzione di più valori da una funzione, quindi se si implementassero i valori restituiti come un elenco, si potrebbe avere una lista vuota che indica che non è stato fornito alcun valore di ritorno.

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

Una distinzione importante qui: io non sto tornando un elenco vuoto se non ci fosse la clausola altro. La lista vuota significa che non c'era alcun valore di ritorno. Se ci fosse un valore di ritorno da un'espressione (diciamo che fosse 3) avresti (3) come il ritorno dall'eval dietro le quinte. Allo stesso modo, la restituzione di più valori da un'espressione causerebbe la presenza di più elementi nell'elenco di ritorno di eval.

Infine, in tutta praticità, si potrebbe davvero tornare nulla se la condizione non riesce e non c'è nessun altro, perché sarebbe un errore in un programma per tentare di catturare il valore di una funzione che non restituisce nulla . In quanto tale, sarebbe compito del programmatore, non della lingua, prendere questo errore.

0

Cosa c'è di sbagliato con solo:

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

?

+0

Quindi, questo è solo il valore predefinito del linguaggio dell'interprete dello schema? Nulla di sbagliato, a meno che tu non stia cercando di implementare lo schema compatibile con R6RS su uno schema compatibile non R6RS :-P –

2

Un numero di Schemi (PLT, Ikarus, Pollo) ha un tipo di vuoto, che è possibile produrre con (nullo).

In PLT almeno, vuoto è quello che ottieni quando lo fai (quando (< 1 0) #t).

(PLT v4 non consente se non c'è una clausola else.)

8

Schema può infatti restituire nessun valori:

> (values) 

In R5RS forma un braccio di se è specificato per restituire un valore specificato. Ciò significa che spetta a te decidere quale valore restituire. Parecchi Schemi hanno scelto di introdurre un valore specifico chiamato "il valore non specificato" e restituisce quel valore. Altri restituiscono "il valore invisibile" # < vuoto> e REPL è scritto in modo che non venga stampato.

> (void) 

In un primo momento si potrebbe pensare, questo è lo stesso (valori), ma notare la differenza:

> (length (list (void))) 
    1 

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

Se # < vuoto> fa parte di una lista, è stampato:

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

Quando il valore restituito non è specificato, è possibile restituire ciò che si desidera; l'utente non può semplicemente contare su quel valore che è lì, mai, o attraverso le implementazioni.

1

Le persone strane restituiscono 'nil o '|| (il simbolo vuoto). Il problema è restituire un simbolo che non può essere restituito entro (eval (alternative if-expr)) per evitare confusione.

Se qualcosa può essere restituito da (eval (alternative if-expr)) e si vuole ancora sapere se siete venuti in questa alternativa o no, si deve mettere in valigia il risultato con ulteriori informazioni:

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

Così, il risultato è un cons cellula. Se la sua auto è #t, hai provato qualcosa. Se è #f, non l'hai fatto.

Problemi correlati