On Wed, Dec 07, 2011 at 10:23:25AM +0100, David Kastrup wrote: > Lilypond is not Scheme but has a more complex syntax. You can use > Scheme in a lot of places with different implications on the grammar > depending on the type of the expression. It would not be feasible to > create a separate Scheme calling operator for every possible type of > expression. And "called just for action" is one such type.
In that case, to be proper, you have to do what the REPL does, which is to wrap the Scheme expression within a call-with-values wherever you process the calling operator. Remember that the continuation can be a case-lambda: (call-with-values (lambda () (values)) (case-lambda (() "No return values") ((x) (format #f "Single value: ~a" x)) (x (format #f "Multiple values: ~a" x)))) (Guile 2.0 has built-in (VM-level) support for case-lambda, which makes this super awesome.) > 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".) > And it is not like Guile has a problem distinguishing content and > package itself (at least Guile 1.8): > > guile> (write *unspecified*) > #<unspecified>guile> (write (values)) > #<values ()>guile> 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. Cheers, Chris.