From: Peter Seibel
Subject: (values)?
Date: 
Message-ID: <m3bs05wwpx.fsf@localhost.localdomain>
It seems--after a few brief experiments in ACL anyway--that if you use
the expression '(values)' somewhere that requires a value, it somehow
gets converted to nil. But at least at the REPL, evaluating (values)
doesn't give you NIL, it gives you nothing. I realize this is a weird
edge case anyway but I'm trying to make sure I understand what the
zero number of values returned by (values) really means. Can someone,
for instance, explain the following REPL session:

  CL-USER(54): (values)
  CL-USER(55): (eq nil (values))
  T
  CL-USER(58): 

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra

From: Nils Goesche
Subject: Re: (values)?
Date: 
Message-ID: <87bs051zhp.fsf@darkstar.cartan>
Peter Seibel <·····@javamonkey.com> writes:

> It seems--after a few brief experiments in ACL anyway--that if you use
> the expression '(values)' somewhere that requires a value, it somehow
> gets converted to nil. But at least at the REPL, evaluating (values)
> doesn't give you NIL, it gives you nothing. I realize this is a weird
> edge case anyway but I'm trying to make sure I understand what the
> zero number of values returned by (values) really means. Can someone,
> for instance, explain the following REPL session:
> 
>   CL-USER(54): (values)
>   CL-USER(55): (eq nil (values))
>   T
>   CL-USER(58): 

When a form returns no values, the REPL won't display any.  If
you pass a form that returns no values as an argument in a
function call, however, read 3.1.2.1.2.3 Function Forms:

# The subforms in the cdr of the original form are evaluated in
# left-to-right order in the current lexical and dynamic
# environments. The primary value of each such evaluation becomes
# an argument to the named function; any additional values
# returned by the subforms are discarded.

And then in the glossary:

# primary value n. (of values resulting from the evaluation of a
#  form) the first value, if any, or else nil if there are no
#  values. ``The primary value returned by truncate is an integer
#  quotient, truncated toward zero.''

So, NIL is passed.

Regards,
-- 
Nils G�sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0
From: Peter Seibel
Subject: Re: (values)?
Date: 
Message-ID: <m3wuitvflz.fsf@localhost.localdomain>
Nils Goesche <···@cartan.de> writes:

> ... read 3.1.2.1.2.3 Function Forms:
> 
> # The subforms in the cdr of the original form are evaluated in
> # left-to-right order in the current lexical and dynamic
> # environments. The primary value of each such evaluation becomes
> # an argument to the named function; any additional values
> # returned by the subforms are discarded.
> 
> And then in the glossary:
> 
> # primary value n. (of values resulting from the evaluation of a
> #  form) the first value, if any, or else nil if there are no
> #  values. ``The primary value returned by truncate is an integer
> #  quotient, truncated toward zero.''
> 
> So, NIL is passed.

Thanks, that's exactly what I was looking for.

-Peter 

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Jochen Schmidt
Subject: Re: (values)?
Date: 
Message-ID: <b5dd1i$q2$05$1@news.t-online.com>
Peter Seibel wrote:

> 
> It seems--after a few brief experiments in ACL anyway--that if you use
> the expression '(values)' somewhere that requires a value, it somehow
> gets converted to nil. But at least at the REPL, evaluating (values)
> doesn't give you NIL, it gives you nothing. I realize this is a weird
> edge case anyway but I'm trying to make sure I understand what the
> zero number of values returned by (values) really means. Can someone,
> for instance, explain the following REPL session:
> 
>   CL-USER(54): (values)
>   CL-USER(55): (eq nil (values))
>   T
>   CL-USER(58):

The first one shows that (values) returns no values.
The second one shows that if one requests a value from a (values)
returning form NIL is given instead.

ciao,
Jochen
From: Jochen Schmidt
Subject: Re: (values)?
Date: 
Message-ID: <b5ddhr$1bh$05$1@news.t-online.com>
Jochen Schmidt wrote:

> Peter Seibel wrote:
> 
>> 
>> It seems--after a few brief experiments in ACL anyway--that if you use
>> the expression '(values)' somewhere that requires a value, it somehow
>> gets converted to nil. But at least at the REPL, evaluating (values)
>> doesn't give you NIL, it gives you nothing. I realize this is a weird
>> edge case anyway but I'm trying to make sure I understand what the
>> zero number of values returned by (values) really means. Can someone,
>> for instance, explain the following REPL session:
>> 
>>   CL-USER(54): (values)
>>   CL-USER(55): (eq nil (values))
>>   T
>>   CL-USER(58):
> 
> The first one shows that (values) returns no values.
> The second one shows that if one requests a value from a (values)
> returning form NIL is given instead.

And btw. if you wonder how to see the difference between (values)
and simply returning NIL:

(multiple-value-list (values)) => ()
(multiple-value-list (values nil)) => (NIL)

ciao,
Jochen
From: Frode Vatvedt Fjeld
Subject: Re: (values)?
Date: 
Message-ID: <2hadfpn1ns.fsf@vserver.cs.uit.no>
Peter Seibel <·····@javamonkey.com> writes:

> Can someone, for instance, explain the following REPL session:
>
>   CL-USER(54): (values)
>   CL-USER(55): (eq nil (values))
>   T
>   CL-USER(58): 

The REPL doesn't evaluate forms for their primary value, but for their
set of returned (zero or more) values. The variable named "/" is
loaded with a list of these values, in effect by something like

  (setq / (multiple-value-list <form>))

This is the eval step of the REPL. The print step is something like

  (loop for value in / do (print value))

The variable named "*" is loaded with the primary value of the
form. The primary value is the first value, or, if there are zero
values, nil. Hence:

  USER: (values)
  USER: (format nil "/ is ~:A and * is ~A." / *)
  "/ is () and * is NIL."
  USER: 

So you see the list of values is empty, and the primary value is NIL.
Now, under normal evaluation rules for function application, each
argument form is evaluated for their primary value. Therefore, when
you evaluate (eq nil (values)) this is reduced to (eq nil nil), which
is true.

Multiple-value-call is a mechanism that provides function application
using an alternative rule for generating the argument list from
argument forms: All of each argument-form's values are appended to the
argument list.

-- 
Frode Vatvedt Fjeld
From: Kaz Kylheku
Subject: Re: (values)?
Date: 
Message-ID: <cf333042.0303211307.e4452e9@posting.google.com>
Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@localhost.localdomain>...
> It seems--after a few brief experiments in ACL anyway--that if you use
> the expression '(values)' somewhere that requires a value, it somehow
> gets converted to nil. But at least at the REPL, evaluating (values)
> doesn't give you NIL, it gives you nothing.

A useful REPL is not literally a naive (LOOP (PRINT (EVAL (READ))));
that is just the high level concept which explains the essential
actions of the listener. A useful REPL must expect the evaluated form
to return multiple values and handle them, for example using logic
like

  (dolist (value (multiple-value-list (eval ...))))
    (print value)))

And of course (multiple-value-list (values)) returns an empty list, so
nothing is printed.

Multiple values have the property that NIL values are automatically
padded if you expect more values than are computed. For example:

  (multiple-value-bind (a b) (values 1) ...)

will bind A to 1, and B to NIL. This naturally extends to the case
when (values) is used in some context that expects just one value; the
padding NIL is supplied instead of an error being signaled.

This is consistent with other areas of the language that have sane
defaulting behavior, like (cdr ()) -> NIL.
From: Rob Warnock
Subject: Re: (values)?
Date: 
Message-ID: <BHOdnUccDaFsBOCjXTWc-g@speakeasy.net>
Kaz Kylheku <···@ashi.footprints.net> wrote:
+---------------
| A useful REPL is not literally a naive (LOOP (PRINT (EVAL (READ))));
| that is just the high level concept which explains the essential
| actions of the listener. A useful REPL must expect the evaluated form
| to return multiple values and handle them, for example using logic
| like
| 
|   (dolist (value (multiple-value-list (eval ...))))
|     (print value)))
| 
| And of course (multiple-value-list (values)) returns an empty list, so
| nothing is printed.
+---------------

IIRC, somebody posted a nice little FORMAT for that a while back:

	(defun mv-eval-print (form)
	  (format t "~&~{~S~%~}" (multiple-value-list (eval form))))

A useful REPL might also print a prompt, which you want the user
to be able to customize (perhaps heavily, with line numbers and
current package and stuff), so you start to get something like the
following pattern:

	(defvar *my-prompt* "> ")

	(defun my-repl ()
	  (loop
	    (if (or (functionp *my-prompt*)
		    (and (symbolp *my-prompt*) (fboundp *my-prompt*)))
	      (funcall *my-prompt*)
	      (format t "~&~a" *my-prompt*))
	    (force-output)		; push out partial line
	    (mv-eval-print (read))))

Of course, after playing with that for about five minutes,
you'll probably decide you really want to handle EOF nicely,
and maybe catch runtime errors and call the debugger yourself
(so you can wrap a couple of top-level restarts around all that),
maybe even special-case a few top-level forms as "commands"
(e.g., ":q" to exit), but that's a story for another time...


-Rob

-----
Rob Warnock, PP-ASEL-IA		<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607