dsill@NSWC-OAS.arpa (Dave Sill) (03/08/88)
In article <1988Mar6.005553.1284@utzoo.uucp> Henry Spencer <utzoo!henry> writes: >This sort of wishlist is the wrong way to go about it, assuming that what >is wanted is a language that will actually be widely implemented and widely >used. If that is to happen, the new language must be either (a) virtually >completely upward-compatible with C and significantly better, or (b) *LOTS* >better than C in at least one area. Personally, I think (b) is the way to go. Sure, upward compatibility would be a major selling point, but it carries with it the dread Backward Compatibility. It's hard to leap when you only use one leg. >Most of the things on this wishlist >are incompatible but unimportant. (Not trivial, necessarily, and in the >abstract I agree with many of them, but that isn't the issue.) Unless some >truly major improvement can be had somewhere else, a language designed from >this wishlist may receive critical acclaim but will never be popular. I disagree that the items on the wishlist are unimportant. True multidimensional arrays, better bit-level data support, a general aggregate constructor mechanism, a better declaration syntax, and a more general macro facility are *major* improvements. Also, although many of the other items on the wishlist are minor, their combined effect would be large. >Remember also that the competition is not just C. C++ is both upward >compatible *and* a major improvement in certain areas. This is a good point. I think more C++ features, if not all, should be considered for inclusion in D. >I used to be very enthusiastic about designing better languages. But I >can no longer work up much enthusiasm for lost causes. I could easily >design a language that would be noticeably better than C. However, I don't >know how to design a language that is *enough* better than C++ for it to >be worth the trouble. I'm sorry, but I just don't think C++ is so good that a *much* better language is not possible. The upward compatibility that makes C++ so attractive initially will probably be its downfall. Most of its weaknesses and limitations are a result of backward compatibility. Don't get me wrong, I think C is an excellent language; and C++ is even better. But I also think a much better language based on C/C++ but with some of the weaknesses removed and better support for current and projected state-of-the-art environments is not only possible, but worthy of pursuit. If nothing else, this discussion serves to highlight the imperfections of C/C++ and to stimulate thought on what could be done better. >Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology >condemned to reinvent it, poorly. |{allegra,ihnp4,decvax,utai}!utzoo!henry Similarly, those who understand C and its limits are less likely to propagate them. ========= The opinions expressed above are mine. "Don't let existing sub-optimal solutions cloud your vision." -- Fred Fish
henry@utzoo.uucp (Henry Spencer) (03/12/88)
> >Most of the things on this wishlist > >are incompatible but unimportant. (Not trivial, necessarily... > > I disagree that the items on the wishlist are unimportant. True > multidimensional arrays, better bit-level data support, a general > aggregate constructor mechanism, a better declaration syntax, and a > more general macro facility are *major* improvements... Au contraire. All they do is reduce the clumsiness of doing those things in C. While that is certainly useful, it is not going to sell people on a new and incompatible language. To do that, you need to show an order-of-magnitude improvement -- overall, not just in a few narrow areas. The things you have listed above are all just icing on the cake; they would *help* sell a language that was already a real contender for other reasons, but by themselves they aren't enough. (Analogously, C++ includes a number of useful, nice small improvements on C, but it would not be worth the trouble without its abstract data types and object-oriented type system.) > I'm sorry, but I just don't think C++ is so good that a *much* better > language is not possible... Oh, I agree it's *possible*; my point is that I don't know how to do it. A little better, yes, that I could do. Fifteen years of active interest in language design, and considerable private work on ideas about the ideal programming language, has given me more than enough thoughts on ways to improve C. But most of them would be, indeed, just icing. My conclusion, after a lot of thought, is that it doesn't matter how much icing you put on if there's no cake underneath. I don't know how to get the order-of-magnitude improvement needed to make lots of converts. That requires at least one quantum leap upward in the power of the language, not just incremental improvements and smoothing down the rough edges. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
tada@athena.mit.edu (Michael Zehr) (03/14/88)
Here's another one for the D wishlist: a function the returns both a % b and a / b at the same time. I know I've had to call those routines with the same values consecutively in code that needed to run fast, and if i understand the library right, they both compute the pair of values, but a different one is returned. Why not give the option of getting them both at the same time? (Of course, this requires returning multiple values ...) ------- michael j zehr "My opinions are my own ... as is my spelling."
wesommer@athena.mit.edu (William Sommerfeld) (03/14/88)
In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >a function the returns both a % b and a / b at the same time. > >I know I've had to call those routines with the same values consecutively >in code that needed to run fast, and if i understand the library right, What library? If you've got a CISC processor with integer divide in microcode (such as the VAX), divide is a single instruction. Modulo might be, too. On just about any reasonable processor, if you're computing someething % or / a power of two, you can turn the operation into an `and' (with (2**n)-1) or `shift right' (by n), respectively, which _is_ in hardware >they >both compute the pair of values, but a different one is returned. Why not >give the option of getting them both at the same time? Well, the VAX has this `ediv' instruction which does both a divide and a modulo.. A good compiler would notice the `common subexpression': c = a / b; d = a % b; and generate the one hairy instruction or function call. I think there's some support in the GNU C compiler for this, but it's turned off on the VAX because `ediv' is apparantly a real turkey of an instruction. - Bill
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/14/88)
In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >a function the returns both a % b and a / b at the same time. This is the first time I recall in the "D" discussion that an useful genuine language feature has been proposed. All you need now is a suitable notation..
sjs@spectral.ctt.bellcore.com (Stan Switzer) (03/15/88)
In article <7451@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: > In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: > >a function the returns both a % b and a / b at the same time. > > This is the first time I recall in the "D" discussion that an useful > genuine language feature has been proposed. All you need now is a > suitable notation.. How about: q = a/b, r = a%b; It works, it is clean, and any respectable compiler will do the right thing.
tim@amdcad.AMD.COM (Tim Olson) (03/15/88)
In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: | | Here's another one for the D wishlist: | | a function the returns both a % b and a / b at the same time. | | I know I've had to call those routines with the same values consecutively | in code that needed to run fast, and if i understand the library right, they | both compute the pair of values, but a different one is returned. Why not | give the option of getting them both at the same time? If you have a good compiler, you can already get this. The low-level divide function for the MetaWare - Am29000 C compiler returns the / value in the specified register, and returns the % value in the standard function return-value register. Therefore, in code like while (n > 0) { buf[i++] = (n%10) + '0'; n /= 10; } only one call to the low-level divide routine is made. -- Tim Olson Advanced Micro Devices (tim@amdcad.amd.com)
henry@utzoo.uucp (Henry Spencer) (03/15/88)
> a function the returns both a % b and a / b at the same time.
ANSI has beaten you to it. See section 4.10.6.2 in the current X3J11 draft,
which defines the "div" function, returning a struct containing both
quotient and remainder. (They chose the wrong definition of division, but
I suppose one can't have everything...)
This is probably the best approach to the issue, since not all machines do
in fact efficiently compute both in the same operation. (The VAX, for
example, has fast instructions that give you either, and a [reportedly]
rather slow instruction that gives you both.) Better to supply both only
when asked.
--
Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology
condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
karl@haddock.ISC.COM (Karl Heuer) (03/15/88)
In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >a function the returns both a % b and a / b at the same time. ANSI C has two flavors of this, in function form: div() and ldiv(). The return value is a structure, which makes it a bit awkward to use if you want both results. Also, unlike the / and % operators, the result is well-defined (guaranteed vax-like) for negative numbers, so it is not necessarily identical to the pair {a/b, a%b}. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
karl@haddock.ISC.COM (Karl Heuer) (03/15/88)
In article <3734@bloom-beacon.MIT.EDU> wesommer@athena.mit.edu (William Sommerfeld) writes: >On just about any reasonable processor, if you're computing someething >% or / a power of two, you can turn the operation into an `and' (with >(2**n)-1) or `shift right' (by n), respectively, which _is_ in hardware Assuming a two's complement representation and that divide rounds toward zero (as on a VAX, the usual standard of a "reasonable processor"), your suggested optimization is not valid if the numerator could be negative. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
rk9005@cca.ucsf.edu (Roland McGrath) (03/15/88)
["The need for D-scussion (was Re: D Wishlist)"] - gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>): } In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: } >a function the returns both a % b and a / b at the same time. } } This is the first time I recall in the "D" discussion that an useful } genuine language feature has been proposed. All you need now is a } suitable notation.. How about: div_t x = div(a, b); ? Why add an operator when there's a standard out there requiring a simple function to do it? -- Roland McGrath ARPA: roland@rtsg.lbl.gov roland@lbl-rtsg.arpa UUCP: ...!ucbvax!lbl-rtsg.arpa!roland
karl@haddock.ISC.COM (Karl Heuer) (03/16/88)
In article <6128@bellcore.bellcore.com> sjs@spectral.UUCP (Stan Switzer) writes: >>>a function the returns both a % b and a / b at the same time. > >How about: q = a/b, r = a%b; >It works, it is clean, and any respectable compiler will do the right thing. That's fine if you actually have variables a and b, but it's not quite that simple if they are more general expressions. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
bs@linus.UUCP (Robert D. Silverman) (03/17/88)
In article <7451@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <3732@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >>a function the returns both a % b and a / b at the same time. > >This is the first time I recall in the "D" discussion that an useful >genuine language feature has been proposed. All you need now is a >suitable notation.. I am a computational number theorist who writes a LOT of code requiring that: A*B/C A*B % C be computed where A,B,C are all 30 bit quantities. The difficulty is that even though the algorithm guarantees that the results of the computations fit in 30 bits, the product A*B may not. I therefore need to make extensive use of any 'emul' and 'ediv' facilities that a computer may have. I have written code which spends 25% of its time JUST doing the above computations (and takes 100's of hours to run). Since there is no 'long long' in C I am forced to write an assember routine which does the computations as follows: remainder = mod_mult(A,B,C,"ient) or the equivalent depending on circumstances. It must first emul A and B then ediv by C. Since most machines which have ediv return the quotient and remainder in two different registers no extra work is required to get the remainder after doing the division. Machines which have such instructions should, In my opinion, generate emul/ediv code whenever it sees A*B/C and only return a run-time arithmetic overflow if the quotient doesn't fit in the appropriate word-size. There should at least be some compiler switch which allows this option. What good are emul and ediv if you can't reach them from higher level languages? Especially on a VAX if you have to call an assembler routine to perform the above, the subroutine call itself can take about as much time as the calculations. A calls on the VAX/780 with 4 arguments takes ~ 17usec. The ediv takes 11.9 and the emul takes 6.8usec. UGLY. There is some need (although I will concede not a lot) for multi-precision arithmetic support. Modern languages are woefully inadequate for the task. Bob Silverman
ok@quintus.UUCP (Richard A. O'Keefe) (03/18/88)
In article <27143@linus.UUCP>, bs@linus.UUCP (Robert D. Silverman) writes: > I am a computational number theorist who writes a LOT of code requiring that: > A*B/C > A*B % C > be computed where A,B,C are all 30 bit quantities. Here is something I knocked together for a Sun-3. It relies on the "inline" processor which comes with SUN's compilers. Some other versions of UNIX have it, but I don't know which. I decided to post this to comp.lang.c because this approach seems to be far the cleanest way of getting assembly code into a C program. You write an ordinary function call, which can be checked by lint just like any other function call. The compiler replaces such function calls by the assembly code of your choice *before* putting the intermediate code through the -O phase, so parts of the code you wrote can actually be fused with parts the compiler wrote. Of course this sort of thing is machine dependent, but the really nice thing is that it doesn't make the code that USES inlined code machine dependent. You can provide ordinary C code for such functions if you want to (great for debugging). Anyway, here's the code. THIS CODE IS PROVIDED FREE TO ILLUSTRATE A TECHNIQUE. I MAKE NO CLAIM THAT ANY PART OF IT FUNCTIONS CORRECTLY. #!/bin/sh cat >muldivrem.il <<'------ EOF ------' | File : muldivrem.il | Author : Richard A. O'Keefe | Defines: in-line expansion for mul_div_rem | The idea is that we want a function | int mul_div_rem(A, B, C, D, Q, R) | /* 32-bit */ int A, B, C, D; | /* 32-bit */ int *Q, *R; | which does | long long int T = A*B+C; | if (D == 0 || T/D overflow) { | *Q = high bits of T, *R = low bits of T; | return 0; | } else { | *Q = T/D, *R = T%D; | return non-zero; | } | The fact that we get the high and low bits of T in the case of an | overflow is due to the definition of the M68020 divs.l instruction, | which doesn't change the destination in this case. More generally, | we might recompute the result. mul_div_rem with D=0 is useful for | getting A*B+C without doing a division. | The point of this file is to have the operation realised by in-line | assembly code, rather than by a C function call with all its overhead. | | Assumptions: | registers d0, d1, d2, and a0 are free. .inline _mul_div_rem,24 movl sp@+,d2 mulsl sp@+,d1:d2 clrl d0 addl sp@+,d2 addxl d0,d1 movl sp@+,d0 blts 1f | if D is zero, don't do the division divsl d0,d1:d2 bvcs 1f | if quotient overflow happened clrl d0 | set the result to 0 1: movl sp@+,a0 movl d2,a0@ movl sp@+,a0 movl d1,a0@ .end ------ EOF ------ ls -l muldivrem.il cat >mdrtest.c <<'------ EOF ------' /* File : mdrtest.c Author : Richard A. O'Keefe Purpose: Test mul_div_rem */ extern int mul_div_rem(); main() { int a, b, c, d, q, r; while ((printf("a,b,c,d:= "), scanf("%d%d%d%d", &a,&b,&c,&d)) == 4) { a = mul_div_rem(a, b, c, d, &q, &r); printf("a=%d, q=%d, r=%d\n", a, q, r); } } ------ EOF ------ ls -l mdrtest.c cat >mdrscript <<'------ EOF ------' #!/bin/sh # File : mdrscript # Author : Richard A. O'Keefe # Purpose: compile mdrtest cc -o mdrtest -O mdrtest.c muldivrem.il ------ EOF ------ ls -l mdrscript
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/19/88)
In article <6128@bellcore.bellcore.com> sjs@spectral.UUCP (Stan Switzer) writes: >How about: > q = a/b, r = a%b; Nice try, but no cigar. It works fine for this simple example, but what if a and b are replaced by more complex expressions, perhaps involving side-effects? This is the same situation that justifies the presence of the op= operators in the language.
karl@haddock.ISC.COM (Karl Heuer) (03/21/88)
In article <27143@linus.UUCP> bs@gauss.UUCP (Robert D. Silverman) writes: >I am a computational number theorist who writes a LOT of code requiring that: >A*B/C [and] A*B%C be computed where A,B,C are all 30 bit quantities. The >difficulty is that even though the algorithm guarantees that the results of >the computations fit in 30 bits, the product A*B may not. I therefore need to >make extensive use of any 'emul' and 'ediv' facilities that a computer may >have. ... Machines which have such instructions should, In my opinion, >generate emul/ediv code whenever it sees A*B/C and only return a run-time >arithmetic overflow if the quotient doesn't fit in the appropriate word-size. Such a special case would be a wart in the language. The "correct" way to do this is to provide an "lmuldiv" function which has the desired semantics (I'd have it return an ldiv_t structure, since it already exists in ANSI C), and encourage vendors to give their compilers the ability to inline it (along with other trivial functions, such as abs()). Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
cik@l.cc.purdue.edu (Herman Rubin) (03/22/88)
In article <3073@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: > In article <27143@linus.UUCP> bs@gauss.UUCP (Robert D. Silverman) writes: > >I am a computational number theorist who writes a LOT of code requiring that: > >A*B/C [and] A*B%C be computed where A,B,C are all 30 bit quantities. The > >difficulty is that even though the algorithm guarantees that the results of > >the computations fit in 30 bits, the product A*B may not. I therefore need to > >make extensive use of any 'emul' and 'ediv' facilities that a computer may > >have. ... Machines which have such instructions should, In my opinion, > >generate emul/ediv code whenever it sees A*B/C and only return a run-time > >arithmetic overflow if the quotient doesn't fit in the appropriate word-size. I think Bob has oversimplified slightly and not asked for enough. What I would like to see is something like u,v = a*b///c (or however he would like to write it; maybe eventually it would become standardized, but it is not now). What a reasonable language needs is the ability of the user to define types and operations at will. C++ allows the introduction of types in some, but not all situations; it does not allow the introduction of operators. > Such a special case would be a wart in the language. The "correct" way to do > this is to provide an "lmuldiv" function which has the desired semantics (I'd > have it return an ldiv_t structure, since it already exists in ANSI C), and > encourage vendors to give their compilers the ability to inline it (along with > other trivial functions, such as abs()). This is precisely what has made it difficult for mathematicians, and all who understand the computer, to make reasonable use of it. To follow the desire of the Mikado to "make the punishment fit the crime," I would sentence all those who would deny the right to use infix notation to others the right to use it for themselves. It is the use of prefix rather than infix notation which makes assembler programming such a chore in 99% of the assemblers. Furthermore, returning a list of values for a function is far different from returning a structure. In the case above, it is likely that everything should be in registers. And it takes no longer to produce the efficient code with a reasonable language than it does to produce the less efficient code with the "warts" removed. In fact, it takes much less time to write a reasonable notation. It takes less time to read someone's reasonable infix notation, even if that is not the way I would write it, than prefix notation, if I have any idea of what is being done. As long as programmers are taught to think in terms of a language, rather than the machine, it will be difficult to get vendors to allow the forcing of inline. -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet
chris@mimsy.UUCP (Chris Torek) (03/23/88)
In article <719@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >This is precisely what has made it difficult for mathematicians, and all who >understand the computer, to make reasonable use of it. To follow the desire >of the Mikado to "make the punishment fit the crime," I would sentence all >those who would deny the right to use infix notation to others the right to >use it for themselves. It is the use of prefix rather than infix notation >which makes assembler programming such a chore in 99% of the assemblers. You must really hate Lisp, and Forth, and RPN calculators, and . . . . >Furthermore, returning a list of values for a function is far different from >returning a structure. If so, the compiler should be improved. There is no theoretical difference (unless you allow variable length lists, but that is not what people were talking about). >As long as programmers are taught to think in terms of a language, rather >than the machine, it will be difficult to get vendors to allow the forcing >of inline. As long as programmers are taught to think in terms of a machine, rather than the language, it will be difficult to get portable code that can be moved to that 1 teraflop computer that will come out tomorrow, then to the 10 teraflop computer that will come out the day after, and then to the 100 teraflop computer that will come out a week from Monday. (When someone finally builds the Ultimate Computer, the one that uses infinite parallelism and quantum effects to achieve the fastest operation that can ever exist, *then* I will give in on this argument.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
shebs%defun.utah.edu.uucp@utah-cs.UUCP (Stanley T. Shebs) (03/23/88)
In article <719@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >[...] It is the use of prefix rather than infix notation >which makes assembler programming such a chore in 99% of the assemblers. Gee, and I thought it was the explicit management of registers and memory that made assembly programming such a chore! CAL (Cray Assembly Language) is infix, but I hadn't noticed that it made much difference to anybody. In case anybody hadn't realized it, this is the same Herman Rubin that's been calling for "portable assembly languages" for years. The suggestion that such a desire is self-contradictory doesn't seem to bother him. The suggestion that he should try doing this himself is met with a request for money upfront, with no concrete evidence that the activity would be useful. He still doesn't seem to have consulted the literature - reading a CACM from, say, 1965 is very educational, particularly if you still have dreams of a "high-level language that allows the programmer to exploit special machine instructions". A language like C didn't get designed in a vacuum, you know - "systems programming languages" was an intensely studied area in the late 60s, and C just happened to be the winner of those long-ago battles... stan shebs shebs@cs.utah.edu
karl@haddock.ISC.COM (Karl Heuer) (03/26/88)
In article <10763@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >In article <719@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: >>Furthermore, returning a list of values for a function is far different from >>returning a structure. > >If so, the compiler should be improved. There is no theoretical difference. Or perhaps the language should be improved. In C, the div() function returns a struct. If I want to add the squares of the two components, I have to write either qr = div(x, y); z = qr.quot * qr.quot + qr.rem * qr.rem; or use a function int f(struct div_t qr) { return (qr.quot * qr.quot + qr.rem * qr.rem); } z = f(div(x, y)); The former requires a throwaway variable; the latter, a throwaway function. In Lisp, you're still returning an aggregate. Things are a little better, because you can tighten the scope: (setq z ((lambda (qr) (+ (* (car qr) (car qr)) (* (cdr qr) (cdr qr)))) (div x y))) In Forth, you can actually return multiple values (as opposed to returning a single value of aggregate type): x @ y @ div dup * swap dup * + z ! There's a certain elegance here which is lacking in the first two. The qr temporary has been absorbed by the syntax of the language, in exactly the same manner as the temporary results of the "*" operator in all three examples. I don't know if this is what Herman was talking about, but in this sense the current C model is lacking. Whether this could be "fixed" in a C-like language is another question. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
cik@l.cc.purdue.edu (Herman Rubin) (03/27/88)
In article <3177@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: > In article <10763@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: > >In article <719@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes: > >>Furthermore, returning a list of values for a function is far different from > >>returning a structure. > > > >If so, the compiler should be improved. There is no theoretical difference. If so, there is at least confusion. As I read K&R, a struct is a memory assignment. In some cases the memory assignment can be transferred to the register file. A list consists of items each of which has its own location. It does not convey the impression that the locations of the items in the list have any relation to each other. One item can be a register, another a byte local to the program, another an external float, we may possibly have both local and external arrays, etc. Generalizing the K&R struct cannot solve the problem. If an external is to be in the object, we have the problem of multiple definition. Furthermore, if I use the same type of list several times, with different arguments each time, it is merely necessary to type in the relative arguments. If we want to use the x.y struct notation and have the list expanded, we can easily do it with a #define statement, but the other way is hard to do. We are dealing with different constructs. > Or perhaps the language should be improved. In C, the div() function returns > a struct. ..... > In Lisp, you're still returning an aggregate. Things are a little better, > because you can tighten the scope: > (setq z > ((lambda (qr) (+ (* (car qr) (car qr)) (* (cdr qr) (cdr qr)))) > (div x y))) > > In Forth, you can actually return multiple values (as opposed to returning a > single value of aggregate type): > x @ y @ div dup * swap dup * + z ! In Lisp, the language certainly suggests that at some time there is a real machine object called qr. The way I am proposing the list, this is never more than a virtual object, and does not need a name. However, the user assigns names to the elements of the list, and refers to them, rather than having to write (car qr) and (cdr qr). I am not saying that the user must not set up the suggested notation, rather that he need not. The Forth example requires that the stack exist. I think that this may make it extremely difficult for a compiler to "do what is natural." It is likely that the "natural" thing to do is far more efficient also. > There's a certain elegance here which is lacking in the first two. The qr > temporary has been absorbed by the syntax of the language, in exactly the same > manner as the temporary results of the "*" operator in all three examples. > > I don't know if this is what Herman was talking about, but in this sense the > current C model is lacking. Whether this could be "fixed" in a C-like > language is another question. Too much elegance, and not enough simplicity. Both versions are unnecessarily complicated. From the standpoint of a computer language, how can there be any difficulty in allowing operators or procedures to produce lists? I doubt that the notation q,r = a _div_ b will confuse a human reader of this article. Whether we have, by ignoring this problem in the past, messed up our current compilers so that it is necessary to do a complete rewriting rather than a fix is another matter. > Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint -- Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907 Phone: (317)494-6054 hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet