guile-devel
[Top][All Lists]
Advanced

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

Re: when and unless


From: Chris K. Jester-Young
Subject: Re: when and unless
Date: Wed, 7 Dec 2011 10:58:34 -0500
User-agent: Mutt/1.5.20 (2009-06-14)

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.



reply via email to

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