2009-03-19 6 views
9

Piszę interpretera programu, aw przypadku if takich jak:Czy możesz zwrócić nic z funkcji na Schemacie?

(if (< 1 0) 'true) 

Wszelkie interpreter Próbowałem po prostu zwraca nowy wiersz. Ale kiedy to zakodowałem, miałam, czy istnieje alternatywne wyrażenie. Co mogę zwrócić w takim przypadku, że nic nie zostanie wydrukowane?

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

Odpowiedz

10

Według R6RS specification:

Jeśli < testów> #f Wydajności i nie < alternatywny> jest określone, wynik wyrażenia jest nieokreślony.

Więc idź na dziko, zwróć wszystko, co chcesz! Chociaż #f lub "() są tym, czego ja osobiście by się spodziewałem.

+1

To samo dotyczy również R5RS. –

+1

Preferuję #f od (jeśli '() ...) da gałąź #t (trzeba przetestować z wartością null?). – Jyaan

1

Po pierwsze, to OK, jeśli wymagać, aby mieć klauzulę innego, jeśli to sprawia, że ​​łatwiejsze. Po drugie, Schemat obsługuje zwracanie wielu wartości z funkcji, więc jeśli zaimplementujesz zwracane wartości jako listę, możesz mieć pustą listę oznaczającą, że nie podano żadnej wartości zwracanej.

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

Ważne rozróżnienie tutaj: Nie zwracam pustej listy, jeśli nie ma innej klauzuli. Pusta lista oznacza, że ​​nie było żadnej wartości zwracanej. Jeśli była jedna wartość zwracana z wyrażenia (powiedzmy, że było 3), to miałbyś (3) jako powrót z eval za kulisami. Podobnie, zwracanie wielu wartości z wyrażenia spowoduje, że lista zwrotów eval będzie zawierała wiele elementów.

Na koniec, praktycznie można zwrócić dowolną wartość, jeśli warunek nie powiedzie się i nie ma innego, ponieważ błąd w programie próbowałby przechwycić wartość funkcji, która nie zwraca niczego . W związku z tym zadaniem tego programisty, a nie języka, byłoby złapanie tego błędu.

0

Co jest nie tak ze tylko:

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

?

+0

To domyślnie brzmi, co robi program tłumacza? Nic złego, chyba że próbujesz wdrożyć zgodny z R6RS Scheme na schemacie niezgodnym z R6RS :-P –

2

Wiele schematów (PLT, Ikarus, Chicken) ma typ pustki, który można wytworzyć za pomocą (void).

W PLT co najmniej nieważne jest to, co dostajesz, gdy robisz (kiedy (< 1 0) #t).

(PLT V4 nie pozwala, jeśli nie zapisu innego).

8

schemat może rzeczywiście nie zwraca wartości:

> (values) 

W R5RS jednoramienne formą, jeżeli określona wartość powrót sprecyzowane. Oznacza to, że od Ciebie zależy, którą wartość zwrócić. Dość kilka schematów zdecydowało się wprowadzić określoną wartość o nazwie "o nieokreślonej wartości" i zwraca tę wartość. Inni zwracają "niewidzialną wartość" # < void>, a REPL jest napisane w taki sposób, że nie drukuje.

> (void) 

Początkowo można by pomyśleć, to jest taki sam jak (wartości), jednak zauważyć różnicę:

> (length (list (void))) 
    1 

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

Jeśli # < void> jest częścią listy, jest drukowany:

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

Gdy wartość zwracana jest nieokreślona, ​​możesz zwrócić to, co chcesz; użytkownik nie może po prostu polegać na tym, że wartość ta istnieje, nigdy lub w różnych implementacjach.

1

Dziwni ludzie wrócą 'nil lub '|| (pusty symbol). Problem polega na zwrocie symbolu, którego nie można zwrócić przez (eval (alternative if-expr)), aby uniknąć nieporozumień.

Jeśli coś może być zwrócony przez (eval (alternative if-expr)) i nadal chcesz wiedzieć, czy był w tej alternatywy, czy też nie, trzeba zapakować wynik z Więcej informacji:

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

Zatem wynik jest minusy komórka. Jeśli jego samochód jest #t, to znaczy, że coś oszacowałeś. Jeśli jest #f, nie zrobiłeś tego.

Powiązane problemy