Can you return nothing from a function in Scheme?

27,440

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.

Share:
27,440
Kai
Author by

Kai

Updated on April 07, 2020

Comments

  • Kai
    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
    Andrey Fedorov about 15 years
    So 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
    Matt Ellis about 15 years
    The same is true in R5RS as well.
  • Jyaan
    Jyaan over 13 years
    I prefer #f since (if '() ...) will give the #t branch (have to test with null?).