Slime (the Emacs mode for Common Lisp) is nothing if not helpful. It autoindents, it completes symbols, it shows backtraces, it fontifies output. It even helpfully points out when an expression returned no values:
CL-USER> (values)
; No value
This is missing the point. Almost all CL functions can find something useful to return — even those, like rplacd
or write
, that are called purely for their side effects usually return one of their arguments, just to make them easier to insert into existing code. Functions producing zero values usually do so not because they have nothing to return, but because they're intended to be used at the REPL, and they don't want to clutter up the output with an uninteresting value. But Slime's helpful comment defeats their efforts. Observe:
CL-USER> (describe 'values)
VALUES is an external symbol in #<PACKAGE "COMMON-LISP">.
Function: #<FUNCTION VALUES>
Its associated name (as in FUNCTION-LAMBDA-EXPRESSION) is VALUES.
The function's arguments are: (&REST VALUES)
Function documentation:
Return all arguments, in order, as values.
On Fri, Mar 24, 2006 07:42:39 AM EST it was compiled from:
SYS:SRC;CODE;EVAL.LISP
Created: Friday, April 15, 2005 09:57:55 AM EDT
; No value
How is this an improvement on a meaningless NIL
?
(Hey, look, a logical pathname! I didn't know anyone used those.)
There's a big difference between no values and one value, NIL. Always converting no values to NIL would destroy information.
ReplyDeleteOf course. But the point of no values is usually to avoid printing anything at the REPL - and in Slime, they don't work for that. So functions like DESCRIBE might as well return some uninteresting value like NIL.
ReplyDeleteIn R5RS, such procedures return an undefined value. In principle, this means anything can be returned and you can't count on it, but most implementations have a special undefined-value object, distinct from zero values, which the REPL printer will not print.
ReplyDeleteIn R6RS, this was loosened to returning an undefined number of undefined values. In practice, though, R6RS implementations still return their unique undefined-value object. R7RS chose to return to the R5RS rule: you can count on getting a single value, but not what it is.
(This matters in Scheme because Scheme does not have CL's magic reduction of more than one value to just one, or zero values to nil; if you pass multiple values to a continuation expecting just one, demons fly out of your nose.)