Can you return nothing from a function in Scheme?
Solution 1
According to the R6RS specification:
If <test> yields #f and no <alternate> is specified, then the result of the expression is unspecified.
So go wild, return anything you want! Although #f or '() are what I, personally, would expect.
Solution 2
Scheme can indeed return no values:
> (values)
In R5RS the one-armed form of if is specified to return an unspecified value. That means it is up to you, to decide which value to return. Quite a few Schemes have chosen to introduce a specific value called "the unspecified value" and returns that value. Others return "the invisible value" #<void> and the REPL is written such that it doesn't print it.
> (void)
At first one might think, this is the same as (values), but note the difference:
> (length (list (void)))
1
> (length (list (values)))
error> context expected 1 value, received 0 values
(Here (list ...) expected 1 value, but received nothing)
If #<void> is part of a list, it is printed:
> (list (void))
(#<void>)
Solution 3
A number of Schemes (PLT, Ikarus, Chicken) have a void type, which you can produce with (void).
In PLT at least, void is what you get when you do (when (< 1 0) #t).
(PLT v4 doesn't allow if without an else clause.)
Solution 4
When the return value is unspecified you can return what you like; the user just can't rely on that value being there, ever, or across implementations.
Solution 5
Weird people would return 'nil
or '||
(the empty symbol). The problem is to return a symbol that cannot be return by (eval (alternative if-expr))
to avoid confusion.
If anything can be returned by (eval (alternative if-expr))
and you still want to know whether you came in this alternative or not, you have to pack the result with more information :
(if (has-alternative if-expr)
(cons #t (eval (alternative if-expr)))
(cons #f #f))
Thus, the result is a cons cell. If its car is #t, then you evaled something. If it is #f, you didn't.
Kai
Updated on April 07, 2020Comments
-
Kai about 4 years
I'm writing a scheme interpreter, and in the case of an if statement such as:
(if (< 1 0) 'true)
Any interpreter I've tried just returns a new prompt. But when I coded this, I had an if for whether there was an alternative expression. What can I return in the if such that nothing gets printed?
(if (has-alternative if-expr) (eval (alternative if-expr)) #f) ;; what do I return here?
-
Andrey Fedorov about 15 yearsSo this just defaults to whatever the scheme interpreter's language does? Nothing wrong, unless you're trying to implement R6RS compatible Scheme on top of a non-R6RS compatible Scheme :-P
-
Matt Ellis about 15 yearsThe same is true in R5RS as well.
-
Jyaan over 13 yearsI prefer #f since (if '() ...) will give the #t branch (have to test with null?).