"Chris K. Jester-Young" <cky...@gmail.com> 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