* when and unless @ 2011-06-30 10:44 Andy Wingo 2011-06-30 21:46 ` Ludovic Courtès 2011-12-05 20:23 ` Andy Wingo 0 siblings, 2 replies; 28+ messages in thread From: Andy Wingo @ 2011-06-30 10:44 UTC (permalink / raw) To: guile-devel I think we should add `when' and `unless' to the default environment. They go like this: (define-syntax when (syntax-rules () ((_ test then then* ...) (if test (begin then then* ... (if #f #f)))))) (define-syntax unless (syntax-rules () ((_ test else else* ...) (if (not test) (begin else else* ... (if #f #f)))))) These are pretty uncontroversial and common, and they make it easier to read code, so let's do it. The only argument I have heard against them is that "when" connotes some connection with time, whereas "if" does not. I agree with this criticism, but "when" is sufficiently common that it shouldn't confuse anyone, and in any case we have modules if someone feels strongly enough to not want these bindings. The trailing (if #f #f) is to indicate that the consequent expressions are evaluated for effect, not for value, and the the return value(s) of `when' and `unless' are not specified. In the future we may cause instances of (if #f #f) used for a value to emit a warning or an error. Regards, Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-06-30 10:44 when and unless Andy Wingo @ 2011-06-30 21:46 ` Ludovic Courtès 2011-07-01 7:50 ` Andy Wingo 2011-12-05 20:23 ` Andy Wingo 1 sibling, 1 reply; 28+ messages in thread From: Ludovic Courtès @ 2011-06-30 21:46 UTC (permalink / raw) To: guile-devel Hello comrade! Andy Wingo <wingo@pobox.com> skribis: > I think we should add `when' and `unless' to the default environment. [...] > These are pretty uncontroversial What?! http://lists.r6rs.org/pipermail/r6rs-discuss/2007-March/thread.html#1856 Here’s another argument: these macros are about writing imperative code, which, as we all know, is Evil. As such, they are unacceptable. (Seriously though, I won’t use them but won’t complain either if they land in Guile.) Thanks, Ludo’. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-06-30 21:46 ` Ludovic Courtès @ 2011-07-01 7:50 ` Andy Wingo 2011-07-01 12:47 ` Ludovic Courtès 0 siblings, 1 reply; 28+ messages in thread From: Andy Wingo @ 2011-07-01 7:50 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel Hi :) On Thu 30 Jun 2011 23:46, ludo@gnu.org (Ludovic Courtès) writes: > http://lists.r6rs.org/pipermail/r6rs-discuss/2007-March/thread.html#1856 Wow, forgot about that one ;) > Here’s another argument: these macros are about writing imperative code, > which, as we all know, is Evil. As such, they are unacceptable. > > (Seriously though, I won’t use them but won’t complain either if they > land in Guile.) OK, cool. One place you might want to use them though is in type checks for Scheme code. We currently don't do very much of that, but probably should in the future. As in: (define (parameter-fluid p) (unless (parameter? p) (wrong-type-arg p 'parameter)) (struct-ref p 1)) The advantage of `unless' over `if' is that the wrong-type-arg is not called in tail position, so the error message sees `parameter-fluid' on the stack. Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-07-01 7:50 ` Andy Wingo @ 2011-07-01 12:47 ` Ludovic Courtès 0 siblings, 0 replies; 28+ messages in thread From: Ludovic Courtès @ 2011-07-01 12:47 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Andy Wingo <wingo@pobox.com> skribis: > One place you might want to use them though is in type checks for Scheme > code. We currently don't do very much of that, but probably should in > the future. As in: > > (define (parameter-fluid p) > (unless (parameter? p) (wrong-type-arg p 'parameter)) > (struct-ref p 1)) > > The advantage of `unless' over `if' is that the wrong-type-arg is not > called in tail position, so the error message sees `parameter-fluid' on > the stack. Oh, interesting, good point! Ludo’. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-06-30 10:44 when and unless Andy Wingo 2011-06-30 21:46 ` Ludovic Courtès @ 2011-12-05 20:23 ` Andy Wingo 2011-12-06 7:48 ` Marijn 2011-12-06 14:39 ` Ludovic Courtès 1 sibling, 2 replies; 28+ messages in thread From: Andy Wingo @ 2011-12-05 20:23 UTC (permalink / raw) To: ludo; +Cc: guile-devel Heya Ludo, On Thu 30 Jun 2011 12:44, Andy Wingo <wingo@pobox.com> writes: > I think we should add `when' and `unless' to the default environment. > > They go like this: > > (define-syntax when > (syntax-rules () > ((_ test then then* ...) > (if test (begin then then* ... (if #f #f)))))) > > (define-syntax unless > (syntax-rules () > ((_ test else else* ...) > (if (not test) (begin else else* ... (if #f #f)))))) WDYT? `unless' is nice for assertions, `when' is its converse, and most Schemes have them. I would like to add them to Guile too. Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-05 20:23 ` Andy Wingo @ 2011-12-06 7:48 ` Marijn 2011-12-06 8:29 ` Alex Shinn 2011-12-06 19:05 ` Chris K. Jester-Young 2011-12-06 14:39 ` Ludovic Courtès 1 sibling, 2 replies; 28+ messages in thread From: Marijn @ 2011-12-06 7:48 UTC (permalink / raw) To: Andy Wingo; +Cc: ludo, guile-devel -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Andy, On 05-12-11 21:23, Andy Wingo wrote: > Heya Ludo, > > On Thu 30 Jun 2011 12:44, Andy Wingo <wingo@pobox.com> writes: > >> I think we should add `when' and `unless' to the default >> environment. >> >> They go like this: >> >> (define-syntax when (syntax-rules () ((_ test then then* ...) (if >> test (begin then then* ... (if #f #f)))))) >> >> (define-syntax unless (syntax-rules () ((_ test else else* ...) >> (if (not test) (begin else else* ... (if #f #f)))))) > > WDYT? `unless' is nice for assertions, `when' is its converse, and > most Schemes have them. I would like to add them to Guile too. Couldn't help but wonder why they don't return the value of the last body form, so I looked around a bit and both CLHS[1] and my racket REPL seem to agree that they should: $ racket Welcome to Racket v5.2.0.4. > (when #t 'hello) 'hello > (unless #f 'hi) 'hi Is there some other source that suggests that the return value should be unspecified? Marijn [1]:http://clhs.lisp.se/Body/m_when_.htm -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk7dyLEACgkQp/VmCx0OL2yAQACeL8y4js+HOZn1IBqFEJEl8n3I i+MAn0TBdz2e1lP9n2EyP9PDlM7ATKUL =nrWC -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 7:48 ` Marijn @ 2011-12-06 8:29 ` Alex Shinn 2011-12-06 11:17 ` David Kastrup 2011-12-06 19:05 ` Chris K. Jester-Young 1 sibling, 1 reply; 28+ messages in thread From: Alex Shinn @ 2011-12-06 8:29 UTC (permalink / raw) To: Marijn; +Cc: Andy Wingo, ludo, guile-devel On Tue, Dec 6, 2011 at 4:48 PM, Marijn <hkBst@gentoo.org> wrote: > > Couldn't help but wonder why they don't return the value of the last > body form, so I looked around a bit and both CLHS[1] and my racket > REPL seem to agree that they should: > > $ racket > Welcome to Racket v5.2.0.4. >> (when #t 'hello) > 'hello >> (unless #f 'hi) > 'hi > > Is there some other source that suggests that the return value should > be unspecified? Because the result is meaningless when the condition is false. CLHS returns nil in this case, but that fits with CL idioms and not Scheme idioms. when and unless are for side-effects - it's better to write (and #t 'hello) if you want the result. R7RS also leaves it unspecified. -- Alex ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 8:29 ` Alex Shinn @ 2011-12-06 11:17 ` David Kastrup 2011-12-06 16:25 ` Andy Wingo 2011-12-07 16:10 ` Chris K. Jester-Young 0 siblings, 2 replies; 28+ messages in thread From: David Kastrup @ 2011-12-06 11:17 UTC (permalink / raw) To: guile-devel Alex Shinn <alexshinn@gmail.com> writes: > On Tue, Dec 6, 2011 at 4:48 PM, Marijn <hkBst@gentoo.org> wrote: >> >> Couldn't help but wonder why they don't return the value of the last >> body form, so I looked around a bit and both CLHS[1] and my racket >> REPL seem to agree that they should: >> >> $ racket >> Welcome to Racket v5.2.0.4. >>> (when #t 'hello) >> 'hello >>> (unless #f 'hi) >> 'hi >> >> Is there some other source that suggests that the return value should >> be unspecified? > > Because the result is meaningless when the condition is false. > > CLHS returns nil in this case, but that fits with CL idioms and > not Scheme idioms. when and unless are for side-effects - it's > better to write (and #t 'hello) if you want the result. > > R7RS also leaves it unspecified. I've actually wondered if it would not make sense to return *unspecified* in the case of the plain else-less if even if the condition is true, namely when you write (if #t #t). There is probably code relying on this to be #t, but frankly, this appears like a recipe for breakage. -- David Kastrup ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 11:17 ` David Kastrup @ 2011-12-06 16:25 ` Andy Wingo 2011-12-06 16:42 ` David Kastrup 2011-12-07 16:10 ` Chris K. Jester-Young 1 sibling, 1 reply; 28+ messages in thread From: Andy Wingo @ 2011-12-06 16:25 UTC (permalink / raw) To: David Kastrup; +Cc: guile-devel On Tue 06 Dec 2011 12:17, David Kastrup <dak@gnu.org> writes: > I've actually wondered if it would not make sense to return > *unspecified* in the case of the plain else-less if even if the > condition is true, namely when you write (if #t #t). I have wondered this too. > There is probably code relying on this to be #t, but frankly, this > appears like a recipe for breakage. Yeah. A first (and probably worthwhile) step would be to warn if such a statement is processed for value. Warning on one-armed ifs in tail position of a function would be harder, as you would have to analyze the call sites of the function. Regards, Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 16:25 ` Andy Wingo @ 2011-12-06 16:42 ` David Kastrup 2011-12-06 17:35 ` Andy Wingo 0 siblings, 1 reply; 28+ messages in thread From: David Kastrup @ 2011-12-06 16:42 UTC (permalink / raw) To: guile-devel Andy Wingo <wingo@pobox.com> writes: > On Tue 06 Dec 2011 12:17, David Kastrup <dak@gnu.org> writes: > >> I've actually wondered if it would not make sense to return >> *unspecified* in the case of the plain else-less if even if the >> condition is true, namely when you write (if #t #t). > > I have wondered this too. > >> There is probably code relying on this to be #t, but frankly, this >> appears like a recipe for breakage. > > Yeah. A first (and probably worthwhile) step would be to warn if such > a statement is processed for value. Well, is it being processed for value if what I do with the value is calling unspecified? on it in order to find out whether I should warn about a function returning a value when it shouldn't? I am working on a language where returning values in certain contexts might at one point of time might lead to the values being used. So I need to implement warnings to that effect in order to find out calls _not_ returning *unspecified*... -- David Kastrup ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 16:42 ` David Kastrup @ 2011-12-06 17:35 ` Andy Wingo 2011-12-06 22:08 ` David Kastrup 0 siblings, 1 reply; 28+ messages in thread From: Andy Wingo @ 2011-12-06 17:35 UTC (permalink / raw) To: David Kastrup; +Cc: guile-devel On Tue 06 Dec 2011 17:42, David Kastrup <dak@gnu.org> writes: > Andy Wingo <wingo@pobox.com> writes: > >> On Tue 06 Dec 2011 12:17, David Kastrup <dak@gnu.org> writes: >> >>> I've actually wondered if it would not make sense to return >>> *unspecified* in the case of the plain else-less if even if the >>> condition is true, namely when you write (if #t #t). >> >> A first (and probably worthwhile) step would be to warn if such >> a statement is processed for value. > > Well, is it being processed for value if what I do with the value is > calling unspecified? on it in order to find out whether I should warn > about a function returning a value when it shouldn't? Yes, it would be. Note, in R5RS scheme, this should be true: (eqv? (if #f #f) (if #f #f)) In R6RS (and R7RS, I think) scheme it does not have any meaning -- implementations are free to do what they like. The reason is that (if #f #f) returns "unspecified values" rather than a canonical "unspecified value". So the implementation may treat it like: (eqv? (values) (values)) which is strictly unspecified, as it is returning an unexpected number of values to a continuation. Guile 1.8: guile> (eqv? (values) (values)) #f Guile 2.0: scheme@(guile-user)> (eqv? (values) (values)) ERROR: In procedure values: ERROR: Throw to key `vm-error' with args `(vm-run "Zero values returned to single-valued continuation" ())'. Not a nicely printed error, but oh well. Guile 2.0 returns a canonical unspecified value in this situation. I would like to consider returning 0 values instead in the future, but figuring out how to do so without breaking the world is tricky. It's useful to hear about your experiences with *unspecified*. > I am working on a language where returning values in certain contexts > might at one point of time might lead to the values being used. So I > need to implement warnings to that effect in order to find out calls > _not_ returning *unspecified*... Have you considered using `(values)' as your way of saying, "I'm not returning any values"? Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 17:35 ` Andy Wingo @ 2011-12-06 22:08 ` David Kastrup 2011-12-06 23:05 ` Chris K. Jester-Young 0 siblings, 1 reply; 28+ messages in thread From: David Kastrup @ 2011-12-06 22:08 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Andy Wingo <wingo@pobox.com> writes: > which is strictly unspecified, as it is returning an unexpected number > of values to a continuation. > > Guile 1.8: > > guile> (eqv? (values) (values)) > #f > > Guile 2.0: > > scheme@(guile-user)> (eqv? (values) (values)) > ERROR: In procedure values: > ERROR: Throw to key `vm-error' with args `(vm-run "Zero values returned to single-valued continuation" ())'. > > Not a nicely printed error, but oh well. > > Guile 2.0 returns a canonical unspecified value in this situation. I > would like to consider returning 0 values instead in the future, but > figuring out how to do so without breaking the world is tricky. It's > useful to hear about your experiences with *unspecified*. > >> I am working on a language where returning values in certain contexts >> might at one point of time might lead to the values being used. So I >> need to implement warnings to that effect in order to find out calls >> _not_ returning *unspecified*... > > Have you considered using `(values)' as your way of saying, "I'm not > returning any values"? Testing for that is not all that much fun. It is also rather useless since pretty much all of the call-for-effect functions of Guile return *unspecified* rather than (values). It is not clear to me why (values) can't just evaluate to a single *unspecified* just like '() evaluates to null. Outside of call-with-values, I don't see much need to treat it special. -- David Kastrup ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 22:08 ` David Kastrup @ 2011-12-06 23:05 ` Chris K. Jester-Young 2011-12-07 9:23 ` David Kastrup 0 siblings, 1 reply; 28+ messages in thread From: Chris K. Jester-Young @ 2011-12-06 23:05 UTC (permalink / raw) To: guile-devel On Tue, Dec 06, 2011 at 11:08:08PM +0100, David Kastrup wrote: > > Have you considered using `(values)' as your way of saying, "I'm not > > returning any values"? > > Testing for that is not all that much fun. It is also rather useless > since pretty much all of the call-for-effect functions of Guile return > *unspecified* rather than (values). You're not really supposed to test for it. In fact, if you don't try to use the value of when, unless, or one-armed ifs, you'll do just fine in general. > It is not clear to me why (values) can't just evaluate to a single > *unspecified* just like '() evaluates to null. Outside of > call-with-values, I don't see much need to treat it special. Implementing that would pretty much either require CPS transforms all around (then you'd look at the arity of the continuation), or else you'd have to be keeping track of the arity of the current continuation some other way. Is it just me, or does that smell like Perl's wantarray? Which brings me to a bigger question---do we even want anything like wantarray? It seems so insanely hacky (to me), even in Perl code. Just my humble opinion, Chris. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 23:05 ` Chris K. Jester-Young @ 2011-12-07 9:23 ` David Kastrup 2011-12-07 15:58 ` Chris K. Jester-Young 0 siblings, 1 reply; 28+ messages in thread From: David Kastrup @ 2011-12-07 9:23 UTC (permalink / raw) To: guile-devel "Chris K. Jester-Young" <cky944@gmail.com> writes: > On Tue, Dec 06, 2011 at 11:08:08PM +0100, David Kastrup wrote: >> > Have you considered using `(values)' as your way of saying, "I'm not >> > returning any values"? >> >> Testing for that is not all that much fun. It is also rather useless >> since pretty much all of the call-for-effect functions of Guile return >> *unspecified* rather than (values). > > You're not really supposed to test for it. 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. >> It is not clear to me why (values) can't just evaluate to a single >> *unspecified* just like '() evaluates to null. Outside of >> call-with-values, I don't see much need to treat it special. > > Implementing that would pretty much either require CPS transforms all > around (then you'd look at the arity of the continuation), or else > you'd have to be keeping track of the arity of the current > continuation some other way. Is it just me, or does that smell like > Perl's wantarray? Well, you'd need to have (call-with-values (lambda () *unspecified*) (lambda x (length x))) => 0 That's the actual clincher I presume? If one takes a look at the Scheme language definition, one finds for one thing: (define (values . things) (call-with-current-continuation (lambda (cont) (apply cont things)))) And, more importantly: Except for continuations created by the call-with-values procedure, all continuations take exactly one value. That means that one _only_ needs to consider the implications on call-with-values continuations. 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> So I still don't quite see the problem that would arise from making (eq? *unspecified* (values)) => #t -- David Kastrup ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-07 9:23 ` David Kastrup @ 2011-12-07 15:58 ` Chris K. Jester-Young 2011-12-08 8:42 ` David Kastrup 0 siblings, 1 reply; 28+ messages in thread From: Chris K. Jester-Young @ 2011-12-07 15:58 UTC (permalink / raw) To: guile-devel 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. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-07 15:58 ` Chris K. Jester-Young @ 2011-12-08 8:42 ` David Kastrup 2011-12-08 15:34 ` Chris K. Jester-Young 2011-12-08 18:10 ` Ian Price 0 siblings, 2 replies; 28+ messages in thread From: David Kastrup @ 2011-12-08 8:42 UTC (permalink / raw) To: guile-devel "Chris K. Jester-Young" <cky944@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 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-08 8:42 ` David Kastrup @ 2011-12-08 15:34 ` Chris K. Jester-Young 2011-12-08 16:10 ` David Kastrup 2011-12-08 18:10 ` Ian Price 1 sibling, 1 reply; 28+ messages in thread From: Chris K. Jester-Young @ 2011-12-08 15:34 UTC (permalink / raw) To: guile-devel On Thu, Dec 08, 2011 at 09:42:36AM +0100, David Kastrup wrote: > 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. That's easy to implement (patch at bottom of post; I tested it). The question for the people on the list to decide is whether it's a good idea. :-) Personally, I don't object to it, but, perhaps others do. Cheers, Chris. * * * diff --git a/libguile/vm-i-system.c b/libguile/vm-i-system.c index 474fe78..6ce5ee3 100644 --- a/libguile/vm-i-system.c +++ b/libguile/vm-i-system.c @@ -1311,7 +1311,7 @@ VM_DEFINE_INSTRUCTION (68, return_values, "return/values", 1, -1, -1) /* Finally null the end of the stack */ NULLSTACK (vals + nvalues - sp); } - else if (nvalues >= 1) + else { /* Multiple values for a single-valued continuation -- here's where I break with guile tradition and try and do something sensible. (Also, @@ -1324,13 +1324,11 @@ VM_DEFINE_INSTRUCTION (68, return_values, "return/values", 1, -1, -1) fp = SCM_FRAME_DYNAMIC_LINK (fp); /* Push first value */ - *++sp = vals[1]; + *++sp = nvalues >= 1 ? vals[1] : SCM_UNSPECIFIED; /* Finally null the end of the stack */ NULLSTACK (vals + nvalues - sp); } - else - goto vm_error_no_values; /* Restore the last program */ program = SCM_FRAME_PROGRAM (fp); ^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-08 15:34 ` Chris K. Jester-Young @ 2011-12-08 16:10 ` David Kastrup 0 siblings, 0 replies; 28+ messages in thread From: David Kastrup @ 2011-12-08 16:10 UTC (permalink / raw) To: guile-devel "Chris K. Jester-Young" <cky944@gmail.com> writes: > On Thu, Dec 08, 2011 at 09:42:36AM +0100, David Kastrup wrote: >> 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. > > That's easy to implement (patch at bottom of post; I tested it). The > question for the people on the list to decide is whether it's a good > idea. :-) Personally, I don't object to it, but, perhaps others do. Well, the bad thing about it is that using *unspecified* explicitly is not equivalent to what Guile does (presuming that it uses (values) whenever it does not return a value) even though it counts as eq?, just like using (values #t #t) is not equivalent to what #t does, but will still count as eq?. It is somewhat similar to how Lua deals with nil (which is a mixture of SCM_UNSPECIFIED and SCM_UNDEFINED in semantics) and tail call argument lists and multiple/single/no value returns. You can figure out the difference between a nil return value and none, but not without tail-calling another function in which you explicitly ask for the number of arguments. Anyway, in Guile there are wagonloads of C functions that return exactly 1 value. I don't think you can always just let them blow up when they don't have a value to deliver. That would be a major migration pain. If you want to discourage people at one time from confusing the two, let the REPL print *unspecified* when that (rather than no value at all) is returned. But I don't think that you should start with this too early. I suppose user-defined C functions, instead of returning SCM_UNSPECIFIED, would have to call something like scm_return_values (SCM_UNDEFINED); instead. -- David Kastrup ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-08 8:42 ` David Kastrup 2011-12-08 15:34 ` Chris K. Jester-Young @ 2011-12-08 18:10 ` Ian Price 1 sibling, 0 replies; 28+ messages in thread From: Ian Price @ 2011-12-08 18:10 UTC (permalink / raw) To: David Kastrup; +Cc: guile-devel David Kastrup <dak@gnu.org> writes: > 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. This seems like a special case of the, I think, CL behaviour where you get a nil for each of the values expected that were not explicitly returned. Not my preference, but certainly not the worst thing you can do. (As an aside, people who want this behaviour can use https://gist.github.com/1359350 which I wrote for dsmith a while back) > 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. Some of us are, I think in the guile community this is a minority view. -- Ian Price "Programming is like pinball. The reward for doing it well is the opportunity to do it again" - from "The Wizardy Compiled" ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 11:17 ` David Kastrup 2011-12-06 16:25 ` Andy Wingo @ 2011-12-07 16:10 ` Chris K. Jester-Young 1 sibling, 0 replies; 28+ messages in thread From: Chris K. Jester-Young @ 2011-12-07 16:10 UTC (permalink / raw) To: guile-devel On Tue, Dec 06, 2011 at 12:17:06PM +0100, David Kastrup wrote: > I've actually wondered if it would not make sense to return > *unspecified* in the case of the plain else-less if even if the > condition is true, namely when you write (if #t #t). This cannot be done without breaking the tail position guarantee that "if" has. i.e., Scheme specifies that for expressions of the form (if TEST THEN ELSE) (if TEST THEN) that THEN and ELSE are both in tail position. Tail position means that the evaluation of THEN or ELSE returns to the caller directly, and there is no chance for the system to intervene, such as by replacing the return value with unspecified. Cheers, Chris. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 7:48 ` Marijn 2011-12-06 8:29 ` Alex Shinn @ 2011-12-06 19:05 ` Chris K. Jester-Young 2011-12-06 19:33 ` Andy Wingo 1 sibling, 1 reply; 28+ messages in thread From: Chris K. Jester-Young @ 2011-12-06 19:05 UTC (permalink / raw) To: guile-devel On Tue, Dec 06, 2011 at 08:48:01AM +0100, Marijn wrote: > Couldn't help but wonder why they don't return the value of the last > body form, so I looked around a bit and both CLHS[1] and my racket > REPL seem to agree that they should: [...] > Is there some other source that suggests that the return value should > be unspecified? This isn't so much because the return value is somehow specified or useful, but rather to avoid breaking tail position. See this discussion I had with Eli Barzilay where this is explained: http://rotty.yi.org/irclogs/freenode/%23scheme/2011-11-02/#e208 (Start at the 07:24 timestamp if the fragment reference isn't working.) Cheers, Chris. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 19:05 ` Chris K. Jester-Young @ 2011-12-06 19:33 ` Andy Wingo 0 siblings, 0 replies; 28+ messages in thread From: Andy Wingo @ 2011-12-06 19:33 UTC (permalink / raw) To: guile-devel On Tue 06 Dec 2011 20:05, "Chris K. Jester-Young" <cky944@gmail.com> writes: > On Tue, Dec 06, 2011 at 08:48:01AM +0100, Marijn wrote: >> Couldn't help but wonder why they don't return the value of the last >> body form, so I looked around a bit and both CLHS[1] and my racket >> REPL seem to agree that they should: > [...] >> Is there some other source that suggests that the return value should >> be unspecified? > > This isn't so much because the return value is somehow specified or > useful, but rather to avoid breaking tail position. See this discussion > I had with Eli Barzilay where this is explained: > > http://rotty.yi.org/irclogs/freenode/%23scheme/2011-11-02/#e208 > > (Start at the 07:24 timestamp if the fragment reference isn't working.) Ah, OK. Indeed this is a very good point, I didn't realize this before. Hummm. Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-05 20:23 ` Andy Wingo 2011-12-06 7:48 ` Marijn @ 2011-12-06 14:39 ` Ludovic Courtès 2011-12-07 14:19 ` Ludovic Courtès 1 sibling, 1 reply; 28+ messages in thread From: Ludovic Courtès @ 2011-12-06 14:39 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Hi, Andy Wingo <wingo@pobox.com> skribis: > On Thu 30 Jun 2011 12:44, Andy Wingo <wingo@pobox.com> writes: > >> I think we should add `when' and `unless' to the default environment. >> >> They go like this: >> >> (define-syntax when >> (syntax-rules () >> ((_ test then then* ...) >> (if test (begin then then* ... (if #f #f)))))) >> >> (define-syntax unless >> (syntax-rules () >> ((_ test else else* ...) >> (if (not test) (begin else else* ... (if #f #f)))))) > > WDYT? `unless' is nice for assertions, `when' is its converse, and most > Schemes have them. I would like to add them to Guile too. Yes, feel free. Ludo’. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-06 14:39 ` Ludovic Courtès @ 2011-12-07 14:19 ` Ludovic Courtès 2011-12-07 14:27 ` David Kastrup 2012-01-07 0:16 ` Andy Wingo 0 siblings, 2 replies; 28+ messages in thread From: Ludovic Courtès @ 2011-12-07 14:19 UTC (permalink / raw) To: guile-devel Hi, ludo@gnu.org (Ludovic Courtès) skribis: > Andy Wingo <wingo@pobox.com> skribis: > >> On Thu 30 Jun 2011 12:44, Andy Wingo <wingo@pobox.com> writes: >> >>> I think we should add `when' and `unless' to the default environment. >>> >>> They go like this: >>> >>> (define-syntax when >>> (syntax-rules () >>> ((_ test then then* ...) >>> (if test (begin then then* ... (if #f #f)))))) >>> >>> (define-syntax unless >>> (syntax-rules () >>> ((_ test else else* ...) >>> (if (not test) (begin else else* ... (if #f #f)))))) >> >> WDYT? `unless' is nice for assertions, `when' is its converse, and most >> Schemes have them. I would like to add them to Guile too. > > Yes, feel free. Like Marijn, it seems more natural for me to return the values of the body’s last expression, rather than *unspecified*. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-07 14:19 ` Ludovic Courtès @ 2011-12-07 14:27 ` David Kastrup 2012-01-07 0:16 ` Andy Wingo 1 sibling, 0 replies; 28+ messages in thread From: David Kastrup @ 2011-12-07 14:27 UTC (permalink / raw) To: guile-devel ludo@gnu.org (Ludovic Courtès) writes: > ludo@gnu.org (Ludovic Courtès) skribis: > >> Andy Wingo <wingo@pobox.com> skribis: >> >>> On Thu 30 Jun 2011 12:44, Andy Wingo <wingo@pobox.com> writes: >>> >>>> I think we should add `when' and `unless' to the default environment. >>>> >>>> They go like this: >>>> >>>> (define-syntax when >>>> (syntax-rules () >>>> ((_ test then then* ...) >>>> (if test (begin then then* ... (if #f #f)))))) >>>> >>>> (define-syntax unless >>>> (syntax-rules () >>>> ((_ test else else* ...) >>>> (if (not test) (begin else else* ... (if #f #f)))))) >>> >>> WDYT? `unless' is nice for assertions, `when' is its converse, and most >>> Schemes have them. I would like to add them to Guile too. >> >> Yes, feel free. > > Like Marijn, it seems more natural for me to return the values of the > body’s last expression, rather than *unspecified*. Can you explain how that would even make sense? You can't return a specified value when the condition is not true since then no form gets evaluated. So where is the point in returning a value that is only sometimes specified? "Sometimes specified" logically is pretty much the same as "unspecified", and then we might return *unspecified* right away. -- David Kastrup ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2011-12-07 14:19 ` Ludovic Courtès 2011-12-07 14:27 ` David Kastrup @ 2012-01-07 0:16 ` Andy Wingo 2012-01-07 22:36 ` Ludovic Courtès 1 sibling, 1 reply; 28+ messages in thread From: Andy Wingo @ 2012-01-07 0:16 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel Hi, On Wed 07 Dec 2011 15:19, ludo@gnu.org (Ludovic Courtès) writes: >>> On Thu 30 Jun 2011 12:44, Andy Wingo <wingo@pobox.com> writes: >>> >>>> I think we should add `when' and `unless' to the default environment. > > Like Marijn, it seems more natural for me to return the values of the > body’s last expression, rather than *unspecified*. Given that there are reasonable cases for `when' and `unless' in side-effecting loops, it is indeed probably best to preserve the <tail sequence> nature of the body of these forms. Are you OK with adding them like this: (define-syntax (when condition stmt stmt* ...) (if condition (begin stmt stmt* ...))) (define-syntax (unless condition stmt stmt* ...) (if (not condition) (begin stmt stmt* ...))) Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2012-01-07 0:16 ` Andy Wingo @ 2012-01-07 22:36 ` Ludovic Courtès 2012-01-20 20:19 ` Andy Wingo 0 siblings, 1 reply; 28+ messages in thread From: Ludovic Courtès @ 2012-01-07 22:36 UTC (permalink / raw) To: guile-devel Hi! Andy Wingo <wingo@pobox.com> skribis: > Are you OK with adding them like this: > > (define-syntax (when condition stmt stmt* ...) > (if condition (begin stmt stmt* ...))) > > (define-syntax (unless condition stmt stmt* ...) > (if (not condition) (begin stmt stmt* ...))) Yes! (‘define-syntax-rule’ I suppose?) Ludo’. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: when and unless 2012-01-07 22:36 ` Ludovic Courtès @ 2012-01-20 20:19 ` Andy Wingo 0 siblings, 0 replies; 28+ messages in thread From: Andy Wingo @ 2012-01-20 20:19 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel Heya, On Sat 07 Jan 2012 23:36, ludo@gnu.org (Ludovic Courtès) writes: > Andy Wingo <wingo@pobox.com> skribis: > >> (define-syntax (when condition stmt stmt* ...) >> (if condition (begin stmt stmt* ...))) >> >> (define-syntax (unless condition stmt stmt* ...) >> (if (not condition) (begin stmt stmt* ...))) > > Yes! > > (‘define-syntax-rule’ I suppose?) Pushed! Cheers, Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2012-01-20 20:19 UTC | newest] Thread overview: 28+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-06-30 10:44 when and unless Andy Wingo 2011-06-30 21:46 ` Ludovic Courtès 2011-07-01 7:50 ` Andy Wingo 2011-07-01 12:47 ` Ludovic Courtès 2011-12-05 20:23 ` Andy Wingo 2011-12-06 7:48 ` Marijn 2011-12-06 8:29 ` Alex Shinn 2011-12-06 11:17 ` David Kastrup 2011-12-06 16:25 ` Andy Wingo 2011-12-06 16:42 ` David Kastrup 2011-12-06 17:35 ` Andy Wingo 2011-12-06 22:08 ` David Kastrup 2011-12-06 23:05 ` Chris K. Jester-Young 2011-12-07 9:23 ` David Kastrup 2011-12-07 15:58 ` Chris K. Jester-Young 2011-12-08 8:42 ` David Kastrup 2011-12-08 15:34 ` Chris K. Jester-Young 2011-12-08 16:10 ` David Kastrup 2011-12-08 18:10 ` Ian Price 2011-12-07 16:10 ` Chris K. Jester-Young 2011-12-06 19:05 ` Chris K. Jester-Young 2011-12-06 19:33 ` Andy Wingo 2011-12-06 14:39 ` Ludovic Courtès 2011-12-07 14:19 ` Ludovic Courtès 2011-12-07 14:27 ` David Kastrup 2012-01-07 0:16 ` Andy Wingo 2012-01-07 22:36 ` Ludovic Courtès 2012-01-20 20:19 ` Andy Wingo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).