Discussion:
[Scheme-reports] "unspecified values"
Andy Wingo
2011-05-19 15:49:27 UTC
Permalink
Suggestion: replace every instance of "an unspecified value", "value is
unspecified", "result is unspecified" and the like with "unspecified
values". This would permit the elegant approach of defining control
constructs with no logical value to return 0 values. This follows the
R6RS.

Regards,

Andy
--
http://wingolog.org/
Alaric Snell-Pym
2011-05-19 16:10:27 UTC
Permalink
Post by Andy Wingo
Suggestion: replace every instance of "an unspecified value", "value is
unspecified", "result is unspecified" and the like with "unspecified
values". This would permit the elegant approach of defining control
constructs with no logical value to return 0 values. This follows the
R6RS.
I was keen to do away with the strange dependence on precisely one value
that was not specified, but it was voted to stick with a single
undefined value being returned from things!

See #68 at http://trac.sacrideo.us/wg/wiki/WG1Ballot2Results
Post by Andy Wingo
Andy
ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
Andy Wingo
2011-05-19 17:10:53 UTC
Permalink
Post by Alaric Snell-Pym
Post by Andy Wingo
Suggestion: replace every instance of "an unspecified value", "value is
unspecified", "result is unspecified" and the like with "unspecified
values". This would permit the elegant approach of defining control
constructs with no logical value to return 0 values. This follows the
R6RS.
I was keen to do away with the strange dependence on precisely one value
that was not specified, but it was voted to stick with a single
undefined value being returned from things!
See #68 at http://trac.sacrideo.us/wg/wiki/WG1Ballot2Results
Unfortunate.

I do not agree with the note that permitting any number of values to be
returned from `set!' et al is incompatible. It is not incompatible with
implementations, as it widens the scope of what they may do. It is not
incompatible with existing programs, as I do not expect existing
implementations to switch -- most will do what they have been doing.
The incompatibility would be for old programs that expect `set!' et al
to return a value -- I argue that these are incorrect programs -- *but
only running on those few implementations that would change*.

So basically an implementation chooses whether it wants the elegance or
the compatibility. That's a fine choice for an implementation to make,
and it does not need to be prescribed by the standard. In the mean time
migrating programmers off of the idea that `set!' produces a portable,
single value is a good thing.

Andy
--
http://wingolog.org/
Jim Rees
2011-05-19 18:50:47 UTC
Permalink
Post by Andy Wingo
I do not agree with the note that permitting any number of values to be
returned from `set!' et al is incompatible. It is not incompatible with
implementations, as it widens the scope of what they may do.....
Requiring a single unspecified value means that:

(let ((x (if #f 'never))) <stuff that does not depend on x>)

is legal Scheme code (based on the interpretation that initializers *must*
return a single value, unspecified or not).

So, allowing implementations to return multiple or zero unspecified values
would actually shrink the language from what it used to be. This is what I
observe the WG tries very hard to avoid, especially if "lots of existing
code" depends on the status quo.

I know nothing about the existing code that depends on this particular
feature. I would personally have preferred "any number", as it's handy for
detecting buggy code.
Emmanuel Medernach
2011-05-19 19:50:25 UTC
Permalink
Post by Jim Rees
Post by Andy Wingo
I do not agree with the note that permitting any number of values to be
returned from `set!' et al is incompatible. It is not incompatible with
implementations, as it widens the scope of what they may do.....
(let ((x (if #f 'never))) <stuff that does not depend on x>)
is legal Scheme code (based on the interpretation that initializers *must*
return a single value, unspecified or not).
So, allowing implementations to return multiple or zero unspecified values
would actually shrink the language from what it used to be. This is what I
observe the WG tries very hard to avoid, especially if "lots of existing
code" depends on the status quo.
I know nothing about the existing code that depends on this particular
feature. I would personally have preferred "any number", as it's handy for
detecting buggy code.
"In the land of the one-armed IF, the people go blind from squinting"
-- Shriram Krishnamurthi

Relying on a value from an expression which could have none is potentially
buggy. I would not go and standardize such "status quo".

In Dr Racket they enforced to always have an 'else' clause. I would suggest
that one armed "if" should return no values.

PS: For me the real problem is elsewhere: I really dislike to have a value
which is an unspecified one, I prefer instead that implementations return
nothing - as in (values) - and to let the standard legitimates some
implementation which wants to return something (as with MIT-Scheme with set!
to have a kind of test-and-set instruction, however I don't know of other
examples)

Best regards,
--
Emmanuel Medernach
Per Bothner
2011-05-20 07:42:24 UTC
Permalink
Post by Emmanuel Medernach
PS: For me the real problem is elsewhere: I really dislike to have a
value which is an unspecified one, I prefer instead that implementations
return nothing - as in (values)
In Kawa set! returns no values. I think this makes the REPL nicer:
set!, define, and similar forms return no values, which prints out as
nothing.
--
--Per Bothner
***@bothner.com http://per.bothner.com/
John Cowan
2011-05-20 14:28:15 UTC
Permalink
Post by Per Bothner
set!, define, and similar forms return no values, which prints out as
nothing.
Every R5RS-compliant Scheme I know of does effectively the same thing:
it returns a distinguished value which the P part of the REPL ignores.
There was a discussion of standardizing this value, but the the WG
decided not to.
--
Si hoc legere scis, nimium eruditionis habes.
Andy Wingo
2011-05-20 15:05:01 UTC
Permalink
Post by John Cowan
Post by Per Bothner
set!, define, and similar forms return no values, which prints out as
nothing.
it returns a distinguished value which the P part of the REPL ignores.
There was a discussion of standardizing this value, but the the WG
decided not to.
I think that Per is saying that if `set!' returns no values, then there
is nothing for P to ignore.

Andy
--
http://wingolog.org/
John Cowan
2011-05-20 15:46:29 UTC
Permalink
Post by Andy Wingo
I think that Per is saying that if `set!' returns no values, then
there is nothing for P to ignore.
Sure. But "making the REPL nicer" is not an argument in favor of set!
returning no values, as the REPL can be just as nice when set! returns a
(distinguished) value.
--
John Cowan ***@ccil.org
http://www.ccil.org/~cowan
Humpty Dump Dublin squeaks through his norse
Humpty Dump Dublin hath a horrible vorse
But for all his kinks English / And his irismanx brogues
Humpty Dump Dublin's grandada of all rogues. --Cousin James
Andy Wingo
2011-05-20 16:00:09 UTC
Permalink
Post by John Cowan
Post by Andy Wingo
I think that Per is saying that if `set!' returns no values, then
there is nothing for P to ignore.
Sure. But "making the REPL nicer" is not an argument in favor of set!
returning no values, as the REPL can be just as nice when set! returns a
(distinguished) value.
I don't know why you insist on this being a *good* strategy, besides
being an allowable one.

For example with this repl:

(define (repl read eval print)
(let loop ()
(call-with-values (lambda () (eval (read)))
(lambda vals
(for-each print vals)
(loop)))))

What does it mean to return three distinguished unspecified values?
Surely it's different than returning one. Yet the user won't know in
such a system. (Incidentally Guile is such a system.)

Andy
--
http://wingolog.org/
Per Bothner
2011-05-20 16:02:04 UTC
Permalink
Post by John Cowan
Post by Andy Wingo
I think that Per is saying that if `set!' returns no values, then
there is nothing for P to ignore.
Sure. But "making the REPL nicer" is not an argument in favor of set!
returning no values, as the REPL can be just as nice when set! returns a
(distinguished) value.
But there is an elegance to doing it this way: If the REPL prints out all
the values of multiple values, then doing nothing when there are no values
doesn't even require special casing. (Some fudging is involved in terms
of when to emit newlines or whitespace.)

Having set! etc return no values also interacts nicely with a set of
alternative syntactic forms where <body> is effectively append-values.
This makes for a very pleasant and composable API, though I won't into
that here. (Imagine the composability of XQuery sequences with the
tool-friendliness of shell with the power of Scheme.)
--
--Per Bothner
***@bothner.com http://per.bothner.com/
Aaron W. Hsu
2011-05-20 16:35:09 UTC
Permalink
Post by Per Bothner
But there is an elegance to doing it this way: If the REPL prints out all
the values of multiple values, then doing nothing when there are no values
doesn't even require special casing.
Indeed, I see no reason why an implementation should not be able to return
no values when there are no "useful" values to consider, and R6RS moved
*away* from overspecifying this to allow implementation to return as many
different values as they felt like doing. I've mentioned before that this
seems to be a much better thing than to force a single value.

However, the votes came in and R5RS' semantics won out.

Aaron W. Hsu
--
Programming is just another word for the lost art of thinking.
Alex Shinn
2011-05-20 16:56:20 UTC
Permalink
Post by Aaron W. Hsu
Post by Per Bothner
But there is an elegance to doing it this way: If the REPL prints out all
the values of multiple values, then doing nothing when there are no values
doesn't even require special casing.
Indeed, I see no reason why an implementation should not be able to return
no values when there are no "useful" values to consider, and R6RS moved
*away* from overspecifying this to allow implementation to return as many
different values as they felt like doing. I've mentioned before that this
seems to be a much better thing than to force a single value.
However, the votes came in and R5RS' semantics won out.
By the way, "me toos" matter on this list (from non-group members).

We won't arbitrarily revisit decisions we've already made,
but if a new argument is raised (not so in this case) or
enough people complain (not yet in this case), we can
re-open the ticket.
--
Alex
Jim Rees
2011-05-20 17:00:16 UTC
Permalink
Post by Aaron W. Hsu
However, the votes came in and R5RS' semantics won out.
Per http://trac.sacrideo.us/wg/wiki/WG1Ballot2Results, 4 out of 5 voters
who submitted "opinions" on this vote seemed to think it was the wrong
choice. The only opinion (that I have access to) in its favor was "Too
many existing programs expect exactly one value". I'm curious about such
programs -- where are they? I'd be happy to fix a few of them here and
there. If enough people volunteer, we can eliminate this argument.

Ooh, Alex says "enough complaints" can re-open the ticket. I hereby
complain. ;-)

-jim
Andre van Tonder
2011-05-20 17:19:50 UTC
Permalink
Post by Aaron W. Hsu
Indeed, I see no reason why an implementation should not be able to return
no values when there are no "useful" values to consider, and R6RS moved
*away* from overspecifying this to allow implementation to return as many
different values as they felt like doing. I've mentioned before that this
seems to be a much better thing than to force a single value.
However, the votes came in and R5RS' semantics won out.
I think the R6RS approach here is superior. It removes a useless postulate
regarding the behavior of portable programs and enlarges the space of conforming
implementations. In removing this weakness/restriction, it seems to me more
Schemely, in the sense of the first paragraph of the introduction of R7RS.

I think that if R7RS wishes to go to the trouble of reintroducing this rather
useless restriction, it will need to accompany it by some very strong
justification.
John Cowan
2011-05-20 20:01:20 UTC
Permalink
Post by Andre van Tonder
I think the R6RS approach here is superior. It removes a useless
postulate regarding the behavior of portable programs and enlarges
the space of conforming implementations. In removing this
weakness/restriction, it seems to me more Schemely, in the sense of
the first paragraph of the introduction of R7RS.
I agree, and voted accordingly. I was in the minority.
Post by Andre van Tonder
I think that if R7RS wishes to go to the trouble of reintroducing this
rather useless restriction, it will need to accompany it by some very
strong justification.
You are mistaken. The only thing the WG1 charter (our constitution; we
didn't choose it) has to say about R6RS is this:

Insofar as practical, the language should be backwards compatible
with the IEEE standard, the R5RS standard, and an appropriate
subset of the R6RS standard.

Note the significant ordering of the terms. When R6RS differs from
R5RS, we need a justification to adopt R6RS, not vice versa.
Similar wording appears in the WG2 charter.
--
Do what you will, John Cowan
this Life's a Fiction ***@ccil.org
And is made up of http://www.ccil.org/~cowan
Contradiction. --William Blake
Andre van Tonder
2011-05-20 20:19:33 UTC
Permalink
Post by John Cowan
Post by Andre van Tonder
I think that if R7RS wishes to go to the trouble of reintroducing this
rather useless restriction, it will need to accompany it by some very
strong justification.
You are mistaken. The only thing the WG1 charter (our constitution; we
Insofar as practical, the language should be backwards compatible
with the IEEE standard, the R5RS standard, and an appropriate
subset of the R6RS standard.
Note the significant ordering of the terms. When R6RS differs from
R5RS, we need a justification to adopt R6RS, not vice versa.
Okay, but these unspecified return values did not even make sense in R5RS. Once
multiple return values became part of Scheme, there was no reason for keeping
them, apart from backward compatibility. But they were a wart even in R5RS.
Alaric Snell-Pym
2011-05-23 10:44:52 UTC
Permalink
Post by Aaron W. Hsu
However, the votes came in and R5RS' semantics won out.
I'm now wondering who actually voted FOR this (but not wondering so hard
as to go digging through everyone's ballots to find out :-)
Post by Aaron W. Hsu
Aaron W. Hsu
ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
John Cowan
2011-05-23 15:47:36 UTC
Permalink
Post by Alaric Snell-Pym
I'm now wondering who actually voted FOR this (but not wondering so
hard as to go digging through everyone's ballots to find out :-)
Always ready to serve.

Cowan, Gleckler, Lucier, Rush, Shinn had R5RS as their top or only
choice. Ganz preferred to always return zero values. Hsu, Medernach,
Snell-Pym had R6RS as their top or only choice. Other WG members did
not vote on this issue.
--
John Cowan ***@ccil.org http://ccil.org/~cowan
You cannot enter here. Go back to the abyss prepared for you! Go back!
Fall into the nothingness that awaits you and your Master. Go! --Gandalf
Aaron W. Hsu
2011-05-23 22:44:07 UTC
Permalink
Post by John Cowan
Always ready to serve.
:-) *chuckle* Thanks John.

Aaron W. Hsu
--
Programming is just another word for the lost art of thinking.
Alaric Snell-Pym
2011-05-23 10:03:13 UTC
Permalink
Post by Emmanuel Medernach
PS: For me the real problem is elsewhere: I really dislike to have a value
which is an unspecified one, I prefer instead that implementations return
nothing - as in (values) - and to let the standard legitimates some
implementation which wants to return something (as with MIT-Scheme with set!
to have a kind of test-and-set instruction, however I don't know of other
examples)
Yes. As I said in WG1 discussion, I think this nonsense of an "undefined
value" (that is then thereby defined...) is daft.

(values) is the logical thing to return if you have nothing to return.

ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
Andy Wingo
2011-05-19 21:42:07 UTC
Permalink
    (let ((x (if #f 'never))) <stuff that does not depend on x>)
is legal Scheme code (based on the interpretation that initializers
*must* return a single value, unspecified or not).
It is currently legal. It runs on all systems that implement R5RS. If
the the final Scheme 2011 came out tomorrow and it said that (if #f #f)
is "unspecified values" instead of "an unspecified value", then the
program still runs on those implementations.

However, it was never in good taste, not even now, before the new report
is out.
I know nothing about the existing code that depends on this particular
feature.   I would personally have preferred "any number", as it's
handy for detecting buggy code.
Yeah, dunno. But there are oodles of implementations out there. If
someone needs this feature from their old program so badly, then they
can choose one of the vast majority of implementations that will
actually produce one single value.

MHO anyway :)

Andy
--
http://wingolog.org/
Alex Shinn
2011-05-21 04:59:51 UTC
Permalink
Post by Andy Wingo
Unfortunate.
I do not agree with the note that permitting any number of values to be
returned from `set!' et al is incompatible.  It is not incompatible with
implementations, as it widens the scope of what they may do.  It is not
incompatible with existing programs, as I do not expect existing
implementations to switch -- most will do what they have been doing.
Yes, it is incompatible with existing programs. One common example is:

(define-syntax time
((time expr)
(let* ((start (current-time))
(res expr))
(report-time 'expr start (current-time))
res)))

This will work fine for arbitrary expressions, including
*set! and I/O operations, so long as they return a single
value as they do in R5RS. I've written quite a lot of
code like this myself, and seen it in many other
people's code.

Another idiom is:

(let* ((foo (bar))
(_ (print "foo: " foo))
(baz (qux foo))
...)

I actually do this quite often when debugging, because
it's easy to remove the print later. Permanent uses are
more likely to result from macro expansions.

Now, you may dislike these idioms, and argue in
particular that the first doesn't work if expr returns
multiple values, but it works fine for users who were
not previously using MV in that context, or perhaps
in any of their code. And using MV at all is still a
contentious issue for some people. There's a
difference between providing a feature, forcing
people to use that feature in new code, and forcing
them to rewrite their old code to support the feature.
We debated this and voted strongly in favor of not
breaking existing code.
--
Alex
Andy Wingo
2011-05-21 08:51:49 UTC
Permalink
Post by Alex Shinn
(define-syntax time
((time expr)
(let* ((start (current-time))
(res expr))
(report-time 'expr start (current-time))
res)))
This is actually an incorrect program. If `expr' returns two values,
you want to return them to the continuation. You need:

(let ((start (current-time)))
(call-with-values (lambda () expr)
(lambda vals
(report-time 'expr start (current-time))
(apply values vals))))
Post by Alex Shinn
Now, you may dislike these idioms, and argue in
particular that the first doesn't work if expr returns
multiple values, but it works fine for users who were
not previously using MV in that context, or perhaps
in any of their code. And using MV at all is still a
contentious issue for some people. There's a
difference between providing a feature, forcing
people to use that feature in new code, and forcing
them to rewrite their old code to support the feature.
We debated this and voted strongly in favor of not
breaking existing code.
If you like this idiom, you are not interested in portable code,
cf. values: if expr returns 0 values, the implementation is allowed to
crash.

I think it's OK to be uninterested in portable code. But don't restrict
all the implementations that *do* want to change because users have
programs that aren't even valid for R5.

Andy
--
http://wingolog.org/
Jim Rees
2011-05-21 13:57:43 UTC
Permalink
Post by Andy Wingo
Post by Alex Shinn
(define-syntax time
((time expr)
(let* ((start (current-time))
(res expr))
(report-time 'expr start (current-time))
res)))
This is actually an incorrect program. If `expr' returns two values,
(let ((start (current-time)))
(call-with-values (lambda () expr)
(lambda vals
(report-time 'expr start (current-time))
(apply values vals))))
Post by Alex Shinn
Now, you may dislike these idioms, and argue in
particular that the first doesn't work if expr returns
multiple values, but it works fine for users who were
not previously using MV in that context, or perhaps
in any of their code. And using MV at all is still a
contentious issue for some people. There's a
difference between providing a feature, forcing
people to use that feature in new code, and forcing
them to rewrite their old code to support the feature.
We debated this and voted strongly in favor of not
breaking existing code.
..and I think Andy is making the point that the code is already broken if MV
is at all possible, or more precisely, the R5RS makes not promises about
it's behavior, because multiple values are potentially not being handled by
a call-with-values.

Now, I have heard why this isn't that big an issue -- that the above code is
not broken *in practice* -- because apparently every major implementation
wraps up multiple values into a single first-class object which can be
passed around until a call-with-values detects it and de-composes it again
(please correct me if I'm wrong).

So, then, it is choices made by implementors that is keeping the above code
working, not the Standard, not the WG. If the WG went with "...returns
unspecified VALUES", the implementors still have the CHOICE to continue what
they're doing to keep the above code from breaking -- i.e. they can choose
NOT to implement a non-wrapped MV implementation, and/or they can choose to
return a single unspecified from set!, (if #f #f), etc.

I think if you're going to depend on the above code forever, the WG could
make it officially portable, by requiring (values...) to return a single
first-class object, one which can be de-composed by call-with-values, and
preferably does not return #t to any standard predicate, but has no other
semantics. (I am NOT recommending this, except to the extent that it makes
your argument more consistent).

-jim
Andy Wingo
2011-05-21 15:10:03 UTC
Permalink
apparently every major implementation wraps up multiple values into a
single first-class object which can be passed around
until a call-with-values detects it and de-composes it again  (please
correct me if I'm wrong).
Guile does not do this. Chez does not either FWIW. Dunno about ikarus;
I think that it also follows the approach I linked to previously:

http://www.cs.indiana.edu/~dyb/pubs/mrvs.pdf
requiring (values...) to return a single first-class object, one which
can be de-composed by call-with-values, and preferably does not return
#t to any standard predicate, but has no other semantics.   (I am NOT
recommending this, except to the extent that it makes your argument
more consistent).
This would be an incompatible change. (It's also not a good
implementation strategy; but that is MHO.)

Andy
--
http://wingolog.org/
John Cowan
2011-05-21 18:24:09 UTC
Permalink
Post by Andy Wingo
apparently every major implementation wraps up multiple values
into a single first-class object which can be passed around until
a call-with-values detects it and de-composes it again  (please
correct me if I'm wrong).
Guile does not do this. Chez does not either FWIW. Dunno about
ikarus; I think that it also follows the approach I linked to
http://www.cs.indiana.edu/~dyb/pubs/mrvs.pdf
Chicken doesn't either: it CPS-converts everything, so that procedures
and continuations are the same thing, and returning multiple values to
a continuation is just calling a procedure with multiple arguments,
IMO a very elegant approach. The only drawback is that the compiler
can usually tell how many arguments a procedure expects, whereas a
continuation has to check at run time how many values it got, and take
corrective action if the number is wrong.

As I posted earlier, Chicken uses the "truncate two or more values
to the first value" strategy. If no values are received but one is
expected, Chicken continuations get the #<undefined> object. This is
the same one returned by standard procedures returning "an undefined
value", and is also returned by the Chicken core procedure `void`.
--
Deshil Holles eamus. Deshil Holles eamus. Deshil Holles eamus.
Send us, bright one, light one, Horhorn, quickening, and wombfruit. (3x)
Hoopsa, boyaboy, hoopsa! Hoopsa, boyaboy, hoopsa! Hoopsa, boyaboy, hoopsa!
--Joyce, Ulysses, "Oxen of the Sun" ***@ccil.org
Andy Wingo
2011-05-22 13:27:29 UTC
Permalink
Chicken ... CPS-converts everything, so that procedures and
continuations are the same thing, and returning multiple values to a
continuation is just calling a procedure with multiple arguments, IMO
a very elegant approach.
Interesting; thanks for the note. Elegant indeed.

Andy
--
http://wingolog.org/
Andre van Tonder
2011-05-21 15:13:08 UTC
Permalink
Post by Alex Shinn
Post by Andy Wingo
Unfortunate.
I do not agree with the note that permitting any number of values to be
returned from `set!' et al is incompatible.  It is not incompatible with
implementations, as it widens the scope of what they may do.  It is not
incompatible with existing programs, as I do not expect existing
implementations to switch -- most will do what they have been doing.
(define-syntax time
((time expr)
(let* ((start (current-time))
(res expr))
(report-time 'expr start (current-time))
res)))
This will work fine for arbitrary expressions, including
*set! and I/O operations, so long as they return a single
value as they do in R5RS.
Arbitrary expressions do not return a single value in R5RS, so
I would say the above macro is buggy even in R5RS. It fails
for something as simple as

(time (values 1 2))

/in R5RS/.

So your example is IMO invalid, unless what you really want is to
return to R4RS. I wonder sometimes... ;)
Alex Shinn
2011-05-21 18:17:24 UTC
Permalink
Post by Andre van Tonder
Arbitrary expressions do not return a single value in R5RS, so
I would say the above macro is buggy even in R5RS.  It fails
for something as simple as
 (time (values 1 2))
/in R5RS/.
So your example is IMO invalid, unless what you really want is to
return to R4RS.  I wonder sometimes... ;)
Wow, everybody immediately replied with exactly
the argument I wrote that they would reply with,
and proceeded to ignore the response I had written.
So I'll include it one more time:

[...] it works fine for users who were
not previously using MV in that context, or perhaps
in any of their code.

It's not a matter whether the code they wrote
generalizes to a wider class of uses or not.
It matters that the code works the way they
were using it before, and with the proposed
change the code would break.
--
Alex
Andre van Tonder
2011-05-21 20:00:59 UTC
Permalink
Post by Alex Shinn
Wow, everybody immediately replied with exactly
the argument I wrote that they would reply with,
and proceeded to ignore the response I had written.
[...] it works fine for users who were
not previously using MV in that context, or perhaps
in any of their code.
generalizes to a wider class of uses or not.
It matters that the code works the way they
were using it before, and with the proposed
change the code would break.
No, the code would not break. The proposed change
(not requiring a return value but still allowing it)
would change little for your purported user.
His preferred implementation will
remain compliant on this /without any change/, and he can continue to
program as before. The only thing that changes is that
he cannot rely on this behavior as being portable.

Note that we are talking about a much milder change than
the nil =/= #f change that Scheme survived
fine.

In any case, if the barrier to change is this high,
then we will NEVER EVER get rid of useless
"features" like this one.

If this is true, I propose that a mechanism for
deprecating misfeatures be instituted.
John Cowan
2011-05-21 20:42:13 UTC
Permalink
No, the code would not break. The proposed change (not requiring
a return value but still allowing it) would change little for your
purported user. His preferred implementation will remain compliant on
this /without any change/, and he can continue to program as before.
The only thing that changes is that he cannot rely on this behavior as
being portable.
Right. That is to say, it works fine on all R5 implementations, but not
on all R6 ones. It is a backwards incompatible change. Such changes
can be made, but they require a threshold that was not met, and there's
no point in moaning about it now. If new *evidence* is brought forward,
that's another matter.
--
[W]hen I wrote it I was more than a little John Cowan
febrile with foodpoisoning from an antique carrot ***@ccil.org
that I foolishly ate out of an illjudged faith http://ccil.org/~cowan
in the benignancy of vegetables. --And Rosta
Andre van Tonder
2011-05-22 21:53:24 UTC
Permalink
Post by John Cowan
No, the code would not break. The proposed change (not requiring
a return value but still allowing it) would change little for your
purported user. His preferred implementation will remain compliant on
this /without any change/, and he can continue to program as before.
The only thing that changes is that he cannot rely on this behavior as
being portable.
Right. That is to say, it works fine on all R5 implementations, but not
on all R6 ones. It is a backwards incompatible change. Such changes
can be made, but they require a threshold that was not met, and there's
no point in moaning about it now. If new *evidence* is brought forward,
that's another matter.
Well, it is only backwards incompatible if you ignore the past few years and all
programs and implementations that took the trouble of adapting to R6RS
to some extent. These implementations are important in the Scheme world. And
let's be honest, they are more important than several of the more outlying ones
that the WG is taking such pains to drag the language backwards to accommodate.

But if WG1-voted decisions are written in stone as you say, then it makes little
sense for this discussion group to even continue. What was the point then of
making the draft public? I will henceforth stop my "moaning"/participation
here. I wish you good luck.
Alex Shinn
2011-05-22 22:45:52 UTC
Permalink
Post by Andre van Tonder
But if WG1-voted decisions are written in stone as you say, then it makes
little sense for this discussion group to even continue.  What was the point
then of making the draft public?  I will henceforth stop my
"moaning"/participation here.  I wish you good luck.
Relax, our decisions are not set in stone, and all
input is appreciated. You and others have made
some excellent points. We just don't want to go
back and forth endlessly on minor issues that
we've already made a decision on for which no
new arguments have been made.
--
Alex
John Cowan
2011-05-23 02:55:01 UTC
Permalink
Post by Andre van Tonder
But if WG1-voted decisions are written in stone as you say, then it makes
little sense for this discussion group to even continue. What was the
point then of making the draft public? I will henceforth stop my
"moaning"/participation here. I wish you good luck.
They are *not* written in stone; they are merely not going to be changed
unless there is new evidence to bring forward.
--
John Cowan ***@ccil.org http://www.ccil.org/~cowan
Dievas dave dantis; Dievas duos duonos --Lithuanian proverb
Deus dedit dentes; deus dabit panem --Latin version thereof
Deity donated dentition;
deity'll donate doughnuts --English version by Muke Tever
God gave gums; God'll give granary --Version by Mat McVeagh
Alaric Snell-Pym
2011-05-23 11:51:20 UTC
Permalink
Post by Andre van Tonder
But if WG1-voted decisions are written in stone as you say, then it makes little
sense for this discussion group to even continue. What was the point then of
making the draft public? I will henceforth stop my "moaning"/participation
here. I wish you good luck.
No! Don't do that!

By all means vent frustration by shouting at each other, but don't let
that get in the way of working together to make Scheme great.

Fatalism and anger will only lead to R7RS just being another R6RS -
swinging too far to the other extreme, driven by rage and bile.

If I were more awesome, I would quote a relevant passage from the Tao Te
Ching here.

ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
Eli Barzilay
2011-05-23 12:18:25 UTC
Permalink
Post by Alaric Snell-Pym
Post by Andre van Tonder
But if WG1-voted decisions are written in stone as you say, then
it makes little sense for this discussion group to even continue.
What was the point then of making the draft public? I will
henceforth stop my "moaning"/participation here. I wish you good
luck.
No! Don't do that!
By all means vent frustration by shouting at each other, but don't
let that get in the way of working together to make Scheme great.
Fatalism and anger will only lead to R7RS just being another R6RS -
swinging too far to the other extreme, driven by rage and bile.
Do you realize that Andre has poured *tons* of efforts on r6rs? I
somehow doubt that characterizing it as "driven by rage and bile" is
going to make him happy.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!
Alaric Snell-Pym
2011-05-23 12:38:49 UTC
Permalink
Post by Eli Barzilay
Post by Alaric Snell-Pym
Post by Andre van Tonder
But if WG1-voted decisions are written in stone as you say, then
it makes little sense for this discussion group to even continue.
What was the point then of making the draft public? I will
henceforth stop my "moaning"/participation here. I wish you good
luck.
No! Don't do that!
By all means vent frustration by shouting at each other, but don't
let that get in the way of working together to make Scheme great.
Fatalism and anger will only lead to R7RS just being another R6RS -
swinging too far to the other extreme, driven by rage and bile.
Do you realize that Andre has poured *tons* of efforts on r6rs? I
somehow doubt that characterizing it as "driven by rage and bile" is
going to make him happy.
I didn't mean R6 was driven by rage and bile, just that R7 would be
driven to the opposite extreme by rage and bile if things get out of hand!

ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
Alaric Snell-Pym
2011-05-23 11:28:36 UTC
Permalink
Post by Alex Shinn
generalizes to a wider class of uses or not.
It matters that the code works the way they
were using it before, and with the proposed
change the code would break.
Yep; and it's then their problem to fix it (and nobody else's) for
having done something that makes assumptions in the first place.

As I said in *my* identikit reply, I often write:

(define (debug label value)
(printf "DEBUG: ~s=~s\n" label value)
value)

...and if I then mistakenly use it in code that uses MV, I then get
around to making it all call-with-valuesy! But if I were writing it as a
library for general publication and consumption, I'd do it properly the
first time round.

Perhaps what should happen, to encourage people to Do It Right The First
Time, is to have some syntax to capture the values of an expression as
some opaque object, and another to return those values.

(values-of (values 1 2)) => unspecified

(let ((x (values-of (values 1 2))))
(unwrap-values x)) => 1 2

My debug procedure would need to become syntax to properly wrap the
value expression, so perhaps it's not enough, though...

ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
John Cowan
2011-05-23 15:57:31 UTC
Permalink
Post by Alaric Snell-Pym
Perhaps what should happen, to encourage people to Do It Right The First
Time, is to have some syntax to capture the values of an expression as
some opaque object, and another to return those values.
That would be:

(define-syntax values-of
(syntax-rules ()
((values-of x) (call-with-values (lambda () x) list))))

(define (unwrap-values v) (apply values v))

Add opacity at your pleasure.
--
John Cowan ***@ccil.org http://www.ccil.org/~cowan
Dievas dave dantis; Dievas duos duonos --Lithuanian proverb
Deus dedit dentes; deus dabit panem --Latin version thereof
Deity donated dentition;
deity'll donate doughnuts --English version by Muke Tever
God gave gums; God'll give granary --Version by Mat McVeagh
Alaric Snell-Pym
2011-05-23 11:19:36 UTC
Permalink
Post by Alex Shinn
(define-syntax time
((time expr)
(let* ((start (current-time))
(res expr))
(report-time 'expr start (current-time))
res)))
This will work fine for arbitrary expressions, including
*set! and I/O operations, so long as they return a single
value as they do in R5RS. I've written quite a lot of
code like this myself, and seen it in many other
people's code.
Ah, but even under R5RS, the expr may not return exactly one expression.
Arbitrary library code is welcome to return (values) or even multiple
useful values. In the former case, the above would have an undefined
consequence, and in the latter case, it'd trim off all but one, as I
read it?
Post by Alex Shinn
(let* ((foo (bar))
(_ (print "foo: " foo))
(baz (qux foo))
...)
I actually do this quite often when debugging, because
it's easy to remove the print later. Permanent uses are
more likely to result from macro expansions.
As a manual debugging idiom it'd be a pain to write (begin (print ...)
#f), but as a macro expansion, that'd be worth it for the generality.
Post by Alex Shinn
Now, you may dislike these idioms, and argue in
particular that the first doesn't work if expr returns
multiple values, but it works fine for users who were
not previously using MV in that context, or perhaps
in any of their code. And using MV at all is still a
contentious issue for some people. There's a
difference between providing a feature, forcing
people to use that feature in new code, and forcing
them to rewrite their old code to support the feature.
Well, the former case is already broken, as arbitrary code may return
arbitrary values.

And the latter case is a useful, if ugly, hack. In similar situations,
I've thrown together a debugging function that can be put anywhere in an
expression, which just prints and then returns its argument. And yes,
I've written this to only handle a single value, but it's my debugging
hack and I'd notice if I used it somewhere I shouldn't ;-)
Post by Alex Shinn
We debated this and voted strongly in favor of not
breaking existing code.
Voted strongly, perhaps - but most of the rationales were against it...

ABS

--
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/
Continue reading on narkive:
Loading...