Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!think.com!hsdndev!husc6!carlton From: carlton@husc10.harvard.edu (david carlton) Newsgroups: comp.lang.scheme Subject: Re: Order of evaluation (was Re: evaluating () should be an error Message-ID: Date: 30 Mar 91 22:31:28 GMT References: <2977@kraftbus.cs.tu-berlin.de> <1991Mar26.155905.12906@daffy.cs.wisc.edu> Sender: news@husc6.harvard.edu Organization: Citizens for Boysenberry Jam Lines: 106 In-reply-to: hieb@heston.cs.indiana.edu's message of 27 Mar 91 15:13:39 GMT In article <1991Mar27.101357.20383@news.cs.indiana.edu> hieb@heston.cs.indiana.edu (Robert Hieb) writes: Scheme is hiding its head in the sand with respect to argument evaluation order and unspecified return values. Arguments do get evaluated in some order and values are returned. Wishing that it weren't so is of little use to the producers and consumers of supposedly portable programs. I simply do not understand what you are trying to say here. "Producers and consumers of supposedly portable programs" certainly can get what they want without having an order of evaluation specified - they simply shouldn't write code which depends on such things. I for one am perfectly capable of writing code which doesn't depend on order of evaluation, as is any competent programmer, and Scheme is hardly the only language (C comes to mind) to refuse to specify an order of evaluation. It would be useful sometimes, to be sure. Very rarely, at least in my code, but such situations do arise. For example, consider the following function: (define reverse! (lambda (list) (let loop ((acc '()) (list list)) (if (not (pair? list)) acc (let ((end (cdr list))) (set-cdr! list acc) (loop list end)))))) What I might prefer to write would be something like (define reverse! (lambda (list) (let loop ((acc '()) (list list)) (if (not (pair? list)) acc (loop (begin (set-cdr! list acc) list) (cdr list)))))) (or perhaps even (define reverse! (lambda (list) (let loop ((acc '()) (list list)) (if (not (pair? list)) acc (loop (set-cdr! list acc) (cdr list)))))) if we are going to have set-cdr! return something useful), which would of course depend on a certain order of evaluation. In particular, it would depend on the second argument being evaluated before the first one. And here we have a problem, because I think that almost all proponents of a specified order of evaluation would want to specify a left to right order of evaluation, and it is simply not the case that your side effects are always going to want to be performed in that order. Here, of course, the fix would be a trivial one, namely to reverse the order that loop takes its arguments, but you can't always do that - the function being called might be a library function, or called a thousand other places in your code before you realize that in one case you really want the arguments to be in the other order for purpose of side effects, or might be a dotted lambda, or you might even want the arguments to come in one order for purposes of side effects in one call and in another order in another call. So what we have is one order of evaluation arbitrarily specified, an order which once in a blue moon will actually turn out to be useful because of side-effects but will in most cases not be the least bit useful, even if side effects are going on and another order of evaluation might allow you to express your procedure with a little less typing. Furthermore, a good compiler should be able to produce just as good code either way in those cases where an explicit order of evaluation will actually help, and, as many people have pointed out, can produce better code in general. Here's a comment on this that I found in the LaTeX source for the R^{3.99}RS: \todo{Freeman: I think an explanation as to why evaluation order is not specified should be included. It should not include any reference to parallel evaluation. Does any existing compiler generate better code because the evaluation order is unspecified? Clinger: yes: T3, MacScheme v2, probably MIT Scheme and Chez Scheme. But that's not the main reason for leaving the order unspecified.} I am curious what their 'main reason' is - can anybody on the committee enlighten us as to that? I would guess that they find a specified order of evaluation aesthetically displeasing and that they think it leads to unclear code, but of course I can't tell. What do people think about the suggestion to have procedures such as the mutation procedures that return an unspecified value in fact return no value at all? This was mentioned as a possibility in the proposal to add multiple return values for Scheme, and T seems to be leaning in that direction. I'm not sure what I think about it or, for that matter, about the whole multiple return value concept - while there are often situations where I want to return multiple values, it is hard for me to think of good notation for that sort of thing. Could someone (if anyone has read this far in my posting) post a list of pros and cons for multiple return values in general and for having mutation procedures in particular return no value? And just what would (or would be allowed to) happen if something returned no value in a situation where a value was expected? david carlton carlton@husc10.harvard.edu