Code Comments
Programming Forum and web based access to our favorite programming groups.I'm not totally following the thread on order of evaluation, but I did pin and see one post asking what everybody thought. I don't care enough about it to discuss ad infinitum, but I have an opinion. In (f a b c) I think f, a, b and c should be evaluated left to right, consistent with the left-to-right order of BEGIN and LAMBDA bodies. Consistency and principle of least surprise are applicable here. Computer languages are not for defining objective mathematics, but for the creation of a human-computer interface, where subjective considerations are important. I do think there should be a special syntax to indicate that expressions can be evaluated in any order, allowing for more optimization than is normally possible. This syntax should be LET. (let ((a e1) (b e2) (c e3)) (f a b c)) This would indicate that e1, e2 and e3 could be evaluated in any order the compiler wishes. Programmers who want a specific order should use LET*. Extra verbiage is justified when you're getting into micro-optimizations. For something like this: ((eval (read)) (read) (read) (read)) I think the behavior should be whatever suprises the fewest newbies. I haven't done a controlled study, but I expect left-to-right evaluation would be the least surprising.
Post Follow-up to this messageBruce Lewis <brlspam@yahoo.com> writes: > I do think there should be a special syntax to indicate that expressions > can be evaluated in any order, allowing for more optimization than is > normally possible. This syntax should be LET. > > (let ((a e1) (b e2) (c e3)) (f a b c)) > > This would indicate that e1, e2 and e3 could be evaluated in any order > the compiler wishes. Programmers who want a specific order should use > LET*. Minor sin: You're destroying the LET -> ((LAMBDA equivalence. But you know that. And perhaps that's not such a big deal. Major sin: You're confusing two different issues: order-of-evaluation and scope. The real difference between LET and LET* is that they have different scope rules. You'd need a third construct, LET/ORDERED, which preserves the scope of LET but allows ordering. (The fourth combination, LET*/UNORDERED, doesn't make sense... but its first-cousin, LET*/PARTIAL-ORDERED, does. Any programmer who uses this construct should be summarily hauled out to the woodshed.) > I think the behavior should be whatever suprises the fewest newbies. I > haven't done a controlled study, but I expect left-to-right evaluation > would be the least surprising. At least if you aren't from the Middle East (though at least in Arabic, the numbers march rightwards -- dunno any Hebrew). Shriram
Post Follow-up to this messageShriram Krishnamurthi <sk@cs.brown.edu> writes: > > At least if you aren't from the Middle East (though at least in > Arabic, the numbers march rightwards -- dunno any Hebrew). Let's say it should match the directionality of how programs are written as strings of characters. In other words, in the language emehcS where the identify function is written (x (x) adbmal) I can see that one would want right-to-left order(*). :-) Matthias (*) Or should that have been )x )x( adbmal( ? Or, maybe, (x (x) abdmal) ?? :) :)
Post Follow-up to this messageBruce Lewis wrote: > I'm not totally following the thread on order of evaluation, but I did > pin and see one post asking what everybody thought. I don't care > enough about it to discuss ad infinitum, but I have an opinion. > > In (f a b c) I think f, a, b and c should be evaluated left to right, > consistent with the left-to-right order of BEGIN and LAMBDA bodies. > Consistency and principle of least surprise are applicable here. > Computer languages are not for defining objective mathematics, but for > the creation of a human-computer interface, where subjective > considerations are important. For function calls, left-to-right is not necessarily the right thing to do, even without optimization. A simple order of evaluation for applications would be: right-to-left; the procedure's value is the last thing you need, and keeping it around while you're evaluating the args is just a waste of register and/or temporary space. Then, there are macros and special forms, where the leftmost symbol controls everything about the rest of the expression. But, to the naked eye, they look exactly like applications, but depending on how they expand, the order of evaluation can be arbitrary relative to the original positions of the expressions. Also, the language provides special notation for asserting sequence; like begin and let*. So, there is little surprise involved: everything is arbitrary order, unless you use one of the sequence asserting forms. Basically, left-to-right imposes unreasonable restraints on the some aspects of implementation, right-to-left would do so for others. You can also see this issue in languages like C/C++. The argument evaluation sequence is related to the expected stack layout on the callee side, and not on the textual sequence of the arguments at the call site. The stack layouts (first arg on top, or last arg on top) dictate different evaluation sequences, if you're trying to keep things simple. For example: foo(1, 2, 3) is either: push 1 ; pascal style push 2 push 3 call foo or push 3 ; C-style push 2 push 1 call foo depending on foo's calling conventions. If you fix the order of evaluation, one of the above alternatives becomes more complex and usually more expensive at runtime. -- A. Kanawati NO.antounk.SPAM@comcast.net
Post Follow-up to this messageAntoun Kanawati <NO.antounk.SPAM@comcast.net> writes: > the procedure's value is the last thing you need, and keeping it around > while you're evaluating the args is just a waste of register and/or > temporary space. I'm not sure what you mean. In a call-by-value setting, you need all the things in the call -- every argument and also the function. There is no "it's the last thing you need". In a call-by-need (lazy) setting, it is even worse: The function is the /first/ thing you need, and it might be the /only/ thing you need. > Then, there are macros and special forms, where the leftmost symbol > controls everything about the rest of the expression. But, to the naked > eye, they look exactly like applications, but depending on how they > expand, the order of evaluation can be arbitrary relative to the > original positions of the expressions. This is one of the problems with macros, indeed. > Basically, left-to-right imposes unreasonable restraints on the > some aspects of implementation, right-to-left would do so for others. "Unreasonable" is in the eye of the beholder. I dispute that the constraints are unreasonable. Leaving the order unspecified, however, does constrain the programmer. Personally, I find those constraints annoying, if not outright unreasonable. > You can also see this issue in languages like C/C++. Oh boy. Now we are defending language design based on what? C and C++? > The argument evaluation sequence is related to the expected stack > layout on the callee side, and not on the textual sequence of the > arguments at the call site. That's an implementation detail which I, as a programmer in a high-level language, should not have to worry about. Matthias
Post Follow-up to this messageAntoun Kanawati <NO.antounk.SPAM@comcast.net> writes: > Basically, left-to-right imposes unreasonable restraints on the > some aspects of implementation, right-to-left would do so for others. Can you name three Scheme implemenetations that actually exploit the fact that they aren't being "unreasonably constrained"? Shriram
Post Follow-up to this messageIn article <nm9u0t6fu22.fsf@no-knife.mit.edu>, Bruce Lewis <brlspam@yahoo.com> wrote: > Computer languages are not for defining objective mathematics, but for > the creation of a human-computer interface, where subjective > considerations are important. You seem to be forgetting that Scheme was created primarily for pedagogic purposes. Thus, the objective mathematical aspects of the language are considered important. If you want a more practical language, use Common Lisp. -- Barry Margolin, barmar@alum.mit.edu Arlington, MA *** PLEASE post questions in newsgroups, not directly to me ***
Post Follow-up to this messageShriram Krishnamurthi <sk@cs.brown.edu> wrote in message news:<w7d4ql64gfy.fsf@cs.brown.edu >... > Antoun Kanawati <NO.antounk.SPAM@comcast.net> writes: > > > Can you name three Scheme implemenetations that actually exploit the > fact that they aren't being "unreasonably constrained"? SISC (which does all loops backwards, i.e. uses a right-to-left order, because comparison to zero may be faster), T with Orbit (which permutes arguments as desired by their cost to minimize shuffling of registers & the stack for temporary storage), Larceny with Twobit (for parallel assignment optimization), and LIAR of MIT Scheme also, I believe, performs some argument ordering analysis, though I know nothing about it except its existence. (I list four because I doubt you'd consider T/Orbit a useful answer.)
Post Follow-up to this message> > Basically, left-to-right imposes unreasonable restraints on the > > Can you name three Scheme implemenetations that actually exploit the > fact that they aren't being "unreasonably constrained"? > > Shriram Yes. What is your point? Will
Post Follow-up to this messagecesuraSPAM@verizon.net (William D Clinger) writes: > > Yes. What is your point? I didn't know of modern Scheme implementations other than Larceny that actually do exploit this. People could defend unspecified ordering as a matter of principle, but many do so as a matter of pragmatics. I wanted to know what the true pragmatics of the situation was, ie, how many blazingly fast Scheme compilers blaze a little faster because of this convenience. (I would be especially interested in hearing just how much faster they run, but that's asking a lot of someone who doesn't have the data handy. This goes to the unreasonableness of the constraint.) Shriram
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.