guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: when and unless


From: David Kastrup
Subject: Re: when and unless
Date: Thu, 08 Dec 2011 09:42:36 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.92 (gnu/linux)

"Chris K. Jester-Young" <address@hidden> writes:

> On Wed, Dec 07, 2011 at 10:23:25AM +0100, David Kastrup wrote:
>
>> Well, you'd need to have
>> 
>> (call-with-values (lambda () *unspecified*) (lambda x (length x))) => 0
> [...]
>> That means that one _only_ needs to consider the implications on
>> call-with-values continuations.
>
> Correct. However, how would you detect whether you're in a context where
> call-with-values is being used? Here are some things that won't work:
>
> 1. You can't walk the stack. Your void expression would be in tail
>    position (it would transfer to the continuation directly, not return
>    to call-with-values---try (call-with-values (lambda () (throw 'foo))
>    (lambda () 42)) and see what the backtrace looks like).
>
> 2. Guile's continuations don't provide meaningful arities: (call/cc
>    (lambda (k) (procedure-minimum-arity k))) always says it takes zero
>    or more arguments. (Same deal applies with Racket, so I presume it's
>    not "just a Guile quirk".)

> In Guile 2.0, multiple values is not a first-class object. Instead, it
> works like Common Lisp: in any context where a single value is needed,
> and multiple values are supplied, then only the first value is used,
> and the rest are thrown away.

>     scheme@(guile-user)> (+ (values 1 2 3) (values 4 5 6))
>     $1 = 5
>     scheme@(guile-user)> (+ (values 1 2 3) (values))
>     ERROR: In procedure values:
>     ERROR: Throw to key `vm-error' with args `(vm-run "Zero values
> returned to single-valued continuation" ())'.
>
>> So I still don't quite see the problem that would arise from making
>> (eq? *unspecified* (values)) => #t
>
> Simply that (values) is not valid to pass to eq?, since eq? is a normal
> function, that thus expects one value for every argument. That this may
> possibly work for Guile 1.8 is simply an accident of its implementation
> of multiple values.

In any way, you have the existing C API which returns single values for
things like scm_eval.

So here is another proposal: (values) is not the same as *unspecified*.
But if you take the first value of a values list in single-value
contexts, there is nothing about that coercion mechanism that would keep
you from using *unspecified* whenever that values list would be empty.

So you would have

(length (call-with-values (lambda () *unspecified*) list)) => 1
(length (call-with-values (lambda () (values)) list)) => 0
(eq? (values) *unspecified*) => #t

After all, you will also have

(length (call-with-values (lambda () (values #t #t)) list)) => 2
(length (call-with-values (lambda () #t) list)) => 1
(eq? (values #t #t) #t) => #t

and nobody seems all too worried about that, I guess.  There will often
be call chaining through C.  You can't throw an error every time
somebody calls a C function like scm_eval or scm_apply or scm_call for
effect and complain whenever the called function exits with the
equivalent of (values), and you can't remove all of the C API at once
and replace it with something that glues together continuations in a
multiple-value passing manner.

-- 
David Kastrup




reply via email to

[Prev in Thread] Current Thread [Next in Thread]