dsill@NSWC-OAS.arpa (Dave Sill) (02/08/88)
>Some years ago I invented the hypothetical notation "e1 ,, e2", which would be >like the comma operator in that it evaluates its left operand before its >right operand, but (unlike comma) the result would be the value of the left >operand. Look what this buys us: > a,, a=b /* displacement operator, like a :=:= b */ > a=(b,, b=a) /* a simple swap */ > x,, ++x /* same as x++; but generalizable */ > free(stack,, stack=stack->next) /* pop stack */ > stack->value,, pop(stack) /* pop and return stacked value */ I like it. Nice and general, fills a gap missing in C. It's not C, but it could be D (it *should* be D, not P (pee?)). Maybe we should start a new newsgroup/mailing-list for the discussion of such things. It seems like a lot of the current discussion here is about things that will never make it into ANSI C such as a power operator, `noalias' :-) et cetera. Sure would improve the S/N ratio for those interested only in C. ========= The opinions expressed above are mine. "The limits of my language mean the limits of my world." -- Ludwig Wittgenstein
rrr@naucse.UUCP (Bob Rose ) (02/08/88)
In article <11702@brl-adm.ARPA>, dsill@NSWC-OAS.arpa (Dave Sill) writes: > >Some years ago I invented the hypothetical notation "e1 ,, e2", which would be > >like the comma operator in that it evaluates its left operand before its > >right operand, but (unlike comma) the result would be the value of the left > >operand. Look what this buys us: > > a,, a=b /* displacement operator, like a :=:= b */ > > a=(b,, b=a) /* a simple swap */ > > x,, ++x /* same as x++; but generalizable */ > > free(stack,, stack=stack->next) /* pop stack */ > > stack->value,, pop(stack) /* pop and return stacked value */ > > I like it. Nice and general, fills a gap missing in C. It's not C, > but it could be D (it *should* be D, not P (pee?)). But wait, we can do better. Why limit yourself to two operands? Let's look at some other programming language (like Icon) and get the correct operator. The magic operator is i(x1, x2, x3, ..., xn) Looks like a function call eh? It's not. i is an integer in the range from 1 to n and the operator produces the outcome of xi. So a simple swap is a = 1(b, b=a); /* much cleaner than ,, */ The the wonderful thing is it wont break any code. So everyone write your ANSI rep now!!!! 8^) BTW my vote for min and max is ?< and ?>. Also why not ?: that produces it first operand if it is not zero else it produces it second that why the getc macro becomes #define getc(file) (*(file)++->char ?: _fillbuf(file)) /* note _fillbuf is smart enough to figure out if there was a '\0' in the input stream or if it was actually at the end of a buffer and of course the buffer size is BUFFSIZE + 1 */ just thinking aload -bob -- Robert R. Rose Northern Arizona University, Box 20023 Flagstaff, AZ 86011 .....!ihnp4!arizona!naucse!rrr
pardo@june.cs.washington.edu (David Keppel) (02/08/88)
In article <11702@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >but it could be D (it *should* be D, not P (pee?)). > >Maybe we should start a new newsgroup/mailing-list for the discussion >of such things. It seems like a lot of the current discussion here is >about things that will never make it into ANSI C such as a power >operator, `noalias' :-) et cetera. Sure would improve the S/N ratio >for those interested only in C. Sounds good to me. I've been collecting interesting ideas about ``D'' off the net for a while. If y'all would like to send me your 1 or two favorite "improvements" to C to be incorporated in "D", I'll send you a summary in response. Not that I intend to write D or P or whatever, but if somebody wants my ideas (take my ideas, please!) ;-D on (Creativity is ... hard to define) Pardo pardo@cs.washington.edu ..!ucbvax!uw-beaver!uw-june!pardo
gpollice@eagle_snax.UUCP ( Sun ECD Software) (02/09/88)
In article <11702@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >>Some years ago I invented the hypothetical notation "e1 ,, e2", which would be >>like the comma operator in that it evaluates its left operand before its >>right operand, but (unlike comma) the result would be the value of the left >>operand. Look what this buys us: >> a,, a=b /* displacement operator, like a :=:= b */ >> a=(b,, b=a) /* a simple swap */ >> x,, ++x /* same as x++; but generalizable */ >> free(stack,, stack=stack->next) /* pop stack */ >> stack->value,, pop(stack) /* pop and return stacked value */ > >I like it. Nice and general, fills a gap missing in C. It's not C, >but it could be D (it *should* be D, not P (pee?)). Actually, the last project course at the late Wang Institute developed a compiler and editor for the D language called Turbo-D. The D language we used was taken from Dijkstra's guarded command language in his book "A Discipline of Programming." For the simple swap you have shown, the D syntax seemed to be much cleaner: a,b := b,a The language had some other features, including non-determinate selection of guards for loops and conditional statements. The project was fun, the language was useful, and the compiler was fast. -- Gary F. Pollice | Remember the Wang Institute!! Sun Microsystems | ARPAnet: gpollice@sun.com Two Federal Street | UUCP: {decwrl,ihnp4,hplabs,ucbvax}!sun!gpollice Billerica, MA 01821 | (617)671-0374
karl@haddock.ISC.COM (Karl Heuer) (02/10/88)
In article <558@naucse.UUCP> rrr@naucse.UUCP (Bob Rose ) writes: >But wait, we can do better [than the proposed ",,"]. Why limit yourself to >two operands? > i(x1, x2, x3, ..., xn) >[where 1 <= i <= n; the result is xi] If `i' is constant, this is no more powerful than `(x1, ..., xi,, ...,, xn)' which produces the same result. If `i' is allowed to be an arbitrary integral expression (which I presume is the case in interpretive Icon), then it is indeed more powerful but also more expensive to compute. Part of the beauty of `,,' is that it has a cost comparable to `,'. >[How about an operator] that produces it first operand if it is not zero else >it produces it second I considered proposing that the `||' operator be so extended (yes, this could break existing code, but only if the operands are nonboolean AND the result is being used in a nonboolean context). After thinking about it, though, I decided that this is a step backwards. In programs that properly distinguish between booleans and integers, there's nothing particularly magic about `compare against zero'. Why should there be a special-purpose notation for `e1 != 0 ? e1 : e2' but not for `e1 != -1 ? e1 : e2', say? What you really want is the `it' pronoun, often used in PDL. IF long-hairy-expression != 0 RETURN it ELSE RETURN other-expression ENDIF Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint KWZH: We need a construct like `e1 UNLESS IT==0 INWHICHCASE e2'. GCJ: Yes, and also `IFONTHEOTHERHAND ... WEMAYSAFELYASSUME'.
sbw@naucse.UUCP (Steve Wampler) (02/10/88)
In article <2523@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: > In article <558@naucse.UUCP> rrr@naucse.UUCP (Bob Rose ) writes: > >But wait, we can do better [than the proposed ",,"]. ... > > i(x1, x2, x3, ..., xn) > >[where 1 <= i <= n; the result is xi] > ... If `i' is allowed to be an arbitrary integral > expression (which I presume is the case in interpretive Icon), then it is > indeed more powerful but also more expensive to compute. Part of the beauty > of `,,' is that it has a cost comparable to `,'. Actually, if 'i' is an arbitrary integral expression, it isn't that much more expensive to implement than if it's a constant - most of the evaluation mechanism is already in place in C (excuse me, 'D'). The only extra expense over computing the value if 'i' is a constant is the cost of evaluating the expression for 'i' and a simple transfer. Sigh, let's just keep postnews happy here... -- Steve Wampler {....!arizona!naucse!sbw}
daveb@geac.UUCP (David Collier-Brown) (02/12/88)
In article <243@eagle_snax.UUCP> gpollice@eagle_snax.UUCP ( Sun ECD Software) writes: | Actually, the last project course at the late Wang Institute developed | a compiler and editor for the D language called Turbo-D. The D language | we used was taken from Dijkstra's guarded command language in his book | "A Discipline of Programming." ... | The language had some other features, including non-determinate selection | of guards for loops and conditional statements. The project was fun, the | language was useful, and the compiler was fast. Can you find out if it can be posted? I'd like a (V)HLL like the Dijkstra language to write hard, complex but non-machine-related things in. A (M)HLL like P would be nice too (:-)). --dave -- David Collier-Brown. {mnetor yunexus utgpu}!geac!daveb Geac Computers International Inc., | Computer Science loses its 350 Steelcase Road,Markham, Ontario, | memory (if not its mind) CANADA, L3R 1B3 (416) 475-0525 x3279 | every 6 months.
karl@haddock.ISC.COM (Karl Heuer) (02/17/88)
In article <563@naucse.UUCP> sbw@naucse.UUCP (Steve Wampler) writes: >> > i(x1, x2, x3, ..., xn) >> >[where 1 <= i <= n; the result is xi] >[Karl Heuer states that the generalization to nonconstant `i' is expensive] >Actually, if 'i' is an arbitrary integral expression, it isn't that much more >expensive to implement than if it's a constant - most of the evaluation >mechanism is already in place in C (excuse me, 'D'). The only extra expense >over computing the value if 'i' is a constant is the cost of evaluating the >expression for 'i' and a simple transfer. Sorry, I stand by my statement. If this `pick' operator is supposed to be a generalization of my proposed `,,' operator, it must preserve the guarantee of evaluating all of the `x?' operands, in left-to-right order. It sounds like you're thinking of the expression equivalent of `switch', which would evaluate exactly one of them. (Which may also be useful, but that's a separate topic.) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
sbw@naucse.UUCP (Steve Wampler) (02/17/88)
In article <2595@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: > In article <563@naucse.UUCP> sbw@naucse.UUCP (Steve Wampler) writes: > >> > i(x1, x2, x3, ..., xn) > >Actually, if 'i' is an arbitrary integral expression, it isn't that much more > >expensive to implement than if it's a constant - most of the evaluation > >expression for 'i' and a simple transfer. > Sorry, I stand by my statement. If this `pick' operator is supposed to be a > generalization of my proposed `,,' operator, it must preserve the guarantee of > evaluating all of the `x?' operands, in left-to-right order. It sounds like > you're thinking of the expression equivalent of `switch', which would evaluate > exactly one of them. (Which may also be useful, but that's a separate topic.) Actually, no. However, I wasn't thinking of this as an exact replacement for the ',,' operator, just as something that does equivalent work. You can evaluate all the operands and then fairly easily make an arbitrary one of them available. Think of 'i(x1, x2, x3,..., xn)' as being analogous to calling a function 'i' that returns its ith argument. Then think of ways to avoid implementing 'i' as a function. I suppose that compared to the ',,' operator, there is the overhead of verifying that 'i' evaluated to the proper range, but that is really a cost of the extra generality, and can be eliminated if 'i' is a constant. Of course, the evaluation order for ',,' is well defined, while the evaluation order (in 'C' at least) for 'i(...)' would match the evaluation order for function calls, which is much messier. (In 'D', however....). I think ',,' is an interesting operator, but I personnally prefer 'i(...)', having used it extensively in Icon - it seems 'more natural' to me. To each his own. -- Steve Wampler {....!arizona!naucse!sbw}
franka@mmintl.UUCP (Frank Adams) (02/19/88)
Any serious effort to design a successor to C (which does not attempt to be upward compatible) should first consider what should be taken out and/or done differently. Adding new things is secondary. The first thing I would remove is the automatic conversion of arrays to pointers. This was an understandable mistake, but a mistake nevertheless. Removing it clears the way for treating arrays as first class objects. (A consequence of this change is that "a[b]" is no longer definable as "*(a + b)". We still have that it is equivalent to "*(&a[0] + b)", but this cannot, of course, be used as a definition.) Second on the list is defaulting of variables. An undeclared variable should be an error, not an int. Likewise for functions. I would favor mandating ANSI-style function prototypes. (Except that the "f(void)" construct would not be needed -- "f()" means a function with no arguments.) Another thing that should go is the assumption that the unit of storage is the byte. The base unit of storage is the bit, and sizeof should return the number of bits in the object. This enables to treat objects smaller than a byte as first class objects. I would also like to do away with having control statements control single statements. For example, instead of writing "if (foo) {stmt1; stmt2;}" I would write "if (foo) stmt1; stmt2; end;". Likewise, I would rewrite the "for" statement as "for <stmts> while (<exp>) next <stmts> do <stmts> end;". The "while" and "do ... while" I would generalize to "loop <stmts> while (<exp>) <stmts> end;". In keeping with the spirit of C, we avoid superfluous words, and keep the ones we do use short. With these changes, the {} statement delimiters become much less useful. I would probably drop them, and add a "begin ... end;" construct for those cases where a local declaration is desired. Another shortcoming to be fixed is the automatic fallthrough for select statements. The default should be exit the statement when a new case is encountered, with an option to fall through. I don't much like the current syntax, either. In any event, the syntax should include specifying multiple values for a case (what is now accomplished by "case a: case b:"). To get even more radical -- with typedefs, enums, const declarations, and (if we add them) inline functions, do we really need the pre-processor any more? Some kind of include statement should be provided, of course. Any decent compiler will optimize "const int foo = 1; if (foo) ... else ... end;", so preprocessor conditional compilation is hardly necessary. I would omit the automatic insertion of a null byte at the end of character constants. If you want nul terminated strings, write the nul. If you want strings with counts, the language should not get in your way. I think I would also drop the convention that 0 is a null pointer. Make "null" a keyword, representing a null pointer of any type. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
karl@haddock.ISC.COM (Karl Heuer) (02/19/88)
In article <580@naucse.UUCP> sbw@naucse.UUCP (Steve Wampler) writes: >In article <2595@haddock.ISC.COM>, karl@haddock.ISC.COM (Karl Heuer) writes: >>It sounds like you're thinking of the expression equivalent of `switch', >>which would evaluate exactly one of [its right operands]. > >Actually, no. However, I wasn't thinking of this as an exact replacement >for the ',,' operator, just as something that does equivalent work. You >can evaluate all the operands and then fairly easily make an arbitrary one >of them available. Yes, you can implement it as (temp[1]=x1, temp[2]=x2, ..., temp[n]=xn, temp[i]) if you're willing to live with the space requirement. (This was noted in the first draft of my earlier article, but I cut it before posting.) >I suppose that ... there is the overhead of verifying that 'i' evaluated to >the proper range ... Actually, it would be well within "the spirit of C" to let an out-of-range selector be an undefined condition. Then the verification can be omitted. >Of course, the evaluation order for ',,' is well defined, while the >evaluation order (in 'C' at least) for 'i(...)' would match the evaluation >order for function calls, which is much messier. And in private correspondence: >Also, note that, in 'C' at least, the types of e1,...,en >must match (this isn't true in Icon). This is important. If we add this `pick' operator but not `,,' on the grounds that the former can simulate the latter, we would have to assert that (a) `pick' guarantees to evaluate its right operands left-to-right, and (b) the right operands must all have the same type if the left operand is nonconstant, but may be of varying types if the left operand is constant. (a) is an arbitrary restriction that shouldn't apply to `pick' for the same reason that it shouldn't apply to function calls (we should let the compiler do whatever is the most efficient thing), and (b) is a kludge of the same magnitude as the recently-proposed enhancement to "++" for non-lvalues. It looks like the best solution is to add both operators! (After all, we're talking about a hypothetical `D' language here.) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
flaps@dgp.toronto.edu (Alan J Rosenthal) (02/19/88)
In article <558@naucse.UUCP> rrr@naucse.UUCP (Bob Rose ) writes: >>[How about an operator] that produces its first operand if it is not zero, >>else it produces its second. In article <2523@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >I considered proposing that the `||' operator be so extended ... >After thinking about it, though, I decided that this is a step backwards... >Why should there be a special-purpose notation for `e1 != 0 ? e1 : e2' but >not for `e1 != -1 ? e1 : e2', say? > >What you really want is the `it' pronoun, often used in PDL. > IF long-hairy-expression != 0 > RETURN it > ELSE > RETURN other-expression > ENDIF An obvious (at least to me) way to extend C to provide this is using the ?: operator. e1 ? e2 : e3 compiles to something vaguely like: calculate e1 jump-if-zero L1 calculate e2 jump-always L2 L1: calculate e3 L2: ... so, something like "e1 ? : e3" could consistently compile to something like: calculate e1 jump-if-zero L1 jump-always L2 L1: calculate e3 L2: ... i.e. just missing the "calculate e2" line, corresponding to the absence of code in this part of the expression. (yes yes, the two adjacent jumps can be reduced to one jump.) Obviously, this would not break any existing code as "e1 ? : e2" is currently a syntax error. And I think this answers Karl Heuer's question quoted above. ajr -- "noalias considered sailaon"
bts@sas.UUCP (Brian T. Schellenberger) (02/19/88)
|> In article <558@naucse.UUCP> rrr@naucse.UUCP (Bob Rose ) writes: |> >But wait, we can do better [than the proposed ",,"]. ... |> > i(x1, x2, x3, ..., xn) |> >[where 1 <= i <= n; the result is xi] |> ... If `i' is allowed to be an arbitrary integral <problems?> Actually, there is a much more natural and powerful way to handle this in D: one of the nicer things about C is the way you can get letters out of strings by doing things like: "abcdefghijklmnopqrstuvwxyz"[letter] Why not extend this and allow in-line arrays? This would allow the "choose" operator to work as, for example: array int {x1, x2, x3, ...}[i] This of course means that "abc" is exactly the same as array char {'a', 'b', 'c', '\0'} . . . just another silly idea. -- --Brian. (Brian T. Schellenberger) ...!mcnc!rti!sas!bts DISCLAIMER: Whereas Brian Schellenberger (hereinafter "the party of the first
gsarff@argus.UUCP (gary sarff) (02/20/88)
I am interested in "alternative" computer languages, and the ICON computer language has structures such as are being talked about here, for a general pick (nth) operator, the exact syntax of <expr>(x1,x2...xn) is used. <expr> can be an integer constant, an arithmetic expression, the name of a function in which case the function will be called with all the xi's as arguments. One can also use &'s instead of commas in which case expression failure of an xi causes failure of the rest of the expressions and evaluation halts there. All three <expr> types are handled uniformly, (ICON is written in C) they all pass through the same C code since something like 2(a,b,c) can be looked at as a function named "2" that returns its second argument, (but all of them get evaluated anyway). -- Gary Sarff {uunet|ihnp4|philabs}!spies!argus!gsarff To program is human, to debug is something best left to the gods. "Spitbol?? You program in a language called Spitbol?" The reason computer chips are so small is that computers don't eat much.
chris@trantor.umd.edu (Chris Torek) (02/20/88)
In article <2718@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >Any serious effort to design a successor to C (which does not attempt to be >upward compatible) should first consider what should be taken out and/or >done differently. Adding new things is secondary. Uh oh. A ray of sensibility on the net! :-) Oddly enough (or perhaps given the impending Standard, it is not so odd), I have been considering the same sort of thing myself. For those who want to wade through details (such as they are), they appear below. One of the nicest things about the C language is what it does NOT do. The language is small enough to learn and comprehend entirely in a short time; the list of language oddities is not empty, but is small (most of them appear below). >The first thing I would remove is the automatic conversion of arrays to >pointers. I am not sure I would make this `first', but I agree. In fact, this is a side effect of what I would do with aggregate types. >Second on the list is defaulting of variables. An undeclared variable >should be an error, not an int. (An undeclared variable *is* an error, unless you claim `register i' leaves `i' undeclared.) >Likewise for functions. agree; unsure about C++/ANSI syntax >Another thing that should go is the assumption that the unit of storage is >the byte. I thought about this; it gets sticky, and I am still unsure. C's structure bitfields are the wrong way to get at bits; in particular, it would be nice to have arrays of bits. But the basic unit of storage has a way of creeping into the rest of the language, no matter how hard one attempts to keep them apart. >I would also like to do away with having control statements control single >statements. For example, instead of writing "if (foo) {stmt1; stmt2;}" I >would write "if (foo) stmt1; stmt2; end;". Likewise, I would rewrite the >"for" statement as "for <stmts> while (<exp>) next <stmts> do <stmts> end;". >The "while" and "do ... while" I would generalize to "loop <stmts> while >(<exp>) <stmts> end;". I disagree with the details, but will note that some human factors studies have shown (and I agree) that a paired `end' is better than a single `end', e.g., `if e stmts endif', `while e stmts endwhile'. On the other hand, other studies have shown that `noise words' inhibit understanding. I am undecided about this. >Another shortcoming to be fixed is the automatic fallthrough for select >statements. agree >To get even more radical -- with typedefs, enums, const declarations, and >(if we add them) inline functions, do we really need the pre-processor any >more? Probably. Inline functions should most certainly be added; they nearly obviate the need for macros. >I would omit the automatic insertion of a null byte at the end of character >constants. If you want nul terminated strings, write the nul. If you want >strings with counts, the language should not get in your way. A general aggregate constructor is necessary. A specific version of one that constructs null-terminated strings might be declared in <strings.h> (or its equivalent). I would like to be able to create C-style arrays (blocks of memory) as easily as `real arrays' (with dope vectors). If I could come up with some way of merging arrays and structures/unions into a single `aggregate' type.... >I think I would also drop the convention that 0 is a null pointer. Make >"null" a keyword, representing a null pointer of any type. This would, at one stroke, eliminate half the confusion that plagues comp.lang.c .... (about 1/3 :-) ) I think the following are important considerations: - the language should be made as small as possible, but no smaller. - we should assume that compilers for this language are going to do a great deal of optimisation; in particular, they will optimise across entire compilations, not just single files. - it should be relatively easy to translate `old C' to the new language. - it might also be a good idea to steal liberally from C++ (which of course steals liberally from SIMULA and others). Very few of my ideas along this line are firm. My biggest worry is that if the language is too small and malleable, it will suffer from the same problems as some of the old dynamically-extensible languages. One solution is to make the language small but the support `library' (including headers that define standard aggregates like C-style arrays and strings) a `part' of the language. -- In-Real-Life: Chris Torek, Univ of MD Computer Science, +1 301 454 7163 (hiding out on trantor.umd.edu until mimsy is reassembled in its new home) Domain: chris@mimsy.umd.edu Path: not easily reachable
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/21/88)
In article <2327@umd5.umd.edu> chris@trantor.umd.edu (Chris Torek) writes: >>Another thing that should go is the assumption that the unit of storage is >>the byte. >I thought about this; it gets sticky, and I am still unsure. C's >structure bitfields are the wrong way to get at bits; in particular, >it would be nice to have arrays of bits. But the basic unit of >storage has a way of creeping into the rest of the language, no >matter how hard one attempts to keep them apart. It isn't that bad, really -- I once went through an earlier C dpANS and identified all the changes necessary to support a distinction between "byte" (smallest accessible storage unit, which could be a bit if you wanted to make it so) and "character" (smallest unit of text). The particular type names I used were "short char" and "char", respectively. It turned out that it wasn't too difficult to make the distinction. The idea lost out to the "multi-byte character" approach embodied in the current draft, which is a pity since that doesn't support bit addressability and it requires specific calls to convert MBC sequences to and from textual units (wchar_t). If you guys really are planning on developing the language D, I hope you'll consider something along these lines. By the way, if that becomes a real project, it should get its own mailing list; there's too many suggestions for changes to C in this newsgroup already..
edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (02/21/88)
> >Another shortcoming to be fixed is the automatic fallthrough for select > >statements. > > agree However, some means of fall through should be provided, BUT it should be explicitly expressed. > > >To get even more radical -- with typedefs, enums, const declarations, and > >(if we add them) inline functions, do we really need the pre-processor any > >more? > > Probably. Inline functions should most certainly be added; they > nearly obviate the need for macros. Not probably, definately we still need the pre-processor. The pre-processor supports a limited form of types as parameters. Example: #define alloc(type) ((type *) malloc(sizeof(type))) Unless you are going to support some other form of polymorphism that will allow the above to be expressed, leave in the pre-processor. > >I think I would also drop the convention that 0 is a null pointer. Make > >"null" a keyword, representing a null pointer of any type. > > This would, at one stroke, eliminate half the confusion that plagues > comp.lang.c .... (about 1/3 :-) ) Unless you require function prototypes to be within scope, null will not do you much good. > > I think the following are important considerations: > > - the language should be made as small as possible, but no smaller. I agree, a very very very important point. > > - we should assume that compilers for this language are going to > do a great deal of optimisation; in particular, they will optimise > across entire compilations, not just single files. Which brings up a question, what happens to the asm statement then. If you have the write you code such that you have no idea where variables are stored, how can you reliable use assemble statement that play with storage. I think the conclusion will be trash asm. -- Eddie Wyatt e-mail: edw@ius1.cs.cmu.edu
jbn@glacier.STANFORD.EDU (John B. Nagle) (02/21/88)
Let me suggest a few ground rules for designing a successor to C: 1) It need not be upward compatible with C, but automatic upward translation should be possible. At the very least, automatic translation with reliable automatic flagging of nonportable constructs should be possible. 2) Syntactic changes should be avoided unless a definite gain can be shown. "I like it better another way" is not sufficient. Changes to syntax tend to arouse opposition all out of proportion to their importance. The major problems in language design are not syntatic. 3) C started life as a weakly typed language, and has been modified slowly into a strongly typed one. This has resulted in some strange semantics. This needs to be dealt with. 4) The basic model of a static language close to the machine should be retained. Attempts to bolt on a very dynamic environment with heavy underlying machinery, along the lines of LISP or Smalltalk, should be resisted. 5) The semantics of types is probably the most important issue to be addressed. 6) The semantics of finite-precision integer arithmetic need to very well thought out. The semantics of arithmetic should be independent of the underlying hardware, so that the same answer is obtained on all machines for all valid operations. (This is possible, and can be done efficiently, but the solutions are not well known.) John Nagle
cdaf@iuvax.UUCP (Charles Daffinger) (02/22/88)
In article <2718@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: > >Any serious effort to design a successor to C (which does not attempt to be >upward compatible) should first consider what should be taken out and/or >done differently. Adding new things is secondary. > [lots of oh, so familiar changes which just don't look like C...] I think the language you want was already designed by Nicolas Wirth: Pascal. -charles -- Charles Daffinger \ Take me to the river / (812) 339-7354 Box 1662 \ drop me in the water / cdaf@iuvax.cs.indiana.edu Bloomington, IN 47402-1662 {pur-ee,rutgers,pyramid,ihnp4}!iuvax!cdaf Home of the Whitewater mailing list: whitewater-request@iuvax.cs.indiana.edu
noise@eneevax.UUCP (Johnson Noise) (02/22/88)
In article <6306@iuvax.UUCP> cdaf@iuvax.UUCP (Charles Daffinger) writes: >In article <2718@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >> >>Any serious effort to design a successor to C (which does not attempt to be >>upward compatible) should first consider what should be taken out and/or >>done differently. Adding new things is secondary. >> >[lots of oh, so familiar changes which just don't look like C...] > >I think the language you want was already designed by Nicolas Wirth: Pascal. > > >-charles > Yeah, I think so. There are even those who want to change = to :=. Computer users (I stress users -- see below) seem to be the biggest complainers of all "scientists". Algol and PL/1 were designed a long time ago, everyone thought that they would be THE programming languages for all humanity/applications. Now people think that ADA and Modula 2 are THE programming languages. Not many people stop to look at history. C was just something Ritchie came up with -- it wasn't a _software_engineering_environment_, just a simple, portable, utility. It has probably become (along with UN*X) the second greatest computer science accomplishment ever. It was not due to some great "design by commitee", just necessity. A guy I work with sometimes asks the question: "now that we have all these great modular languages like ADA and Modula 2, I would think there would be more software using them". This has to do with Mac stuff which is mostly written in C. The answer is simple: computer systems people (I stress systems people -- see below) are more interested in getting the job done. Let's face it, a compiler is just a tool. It does not write code for you, it does not find algorithmic errors for you, it is just a way to avoid assembly (this is the reason FORTRAN is the first greatest computer science accomplishment). If you don't like C, don't use it. There must be at least 100 different programming languages, none of which are radically different from Algol, FORTRAN, or LISP. All three of these were invented in the late 50's-early 60's, so I think you can find what you are looking for in some variant. C was designed as a systems implementation language, not THE language for all humanity/applications. I think it does a very, very good job. What most people are suggesting (with respect to D) is another Algol, PL/1, ADA, Modula 2 and whatever else comes up in the next five years. It will suffer the same fate: crash and burn. #define systems_person one who gets the job done #ifdef systems_person #define user !systems_person #else #define user one who waits for someone|something to do the job for him #endif I think Henry Spencer's quote says it all: "those who do not understand UNIX are condemned to reinvent it, poorly". This is not meant as a flame, just my personal observations.
mcdonald@uxe.cso.uiuc.edu (02/22/88)
I find it hard to believe that a successor to C is needed or would be appreciated. I come to this as a former 100% Fortran (and assembler) programmer who now uses C about 80 % of the time. C does have a few, minor defects (for instance, I will never , ever understand the syntax of declarations; I have had a guru make up a huge chart listing dozens of them, which I carry in my wallet.) So does every other language. C does one thing extremely well: convert the heart of the machine operations of a byte-addressible, conventional processor (i.e. the PDP11) into a nice higher language. It is pleasantly compact, and very full of nice shortcuts (e.g. "string"[i] ). If you dislike C , try other languages: Fortran, Pascal, Ada ,Modula 2. Me, well , I like C and Fortran and loathe the rest. But if a new language is to be designed, and done really well, it won't be done by committee. For the perfect example look in comp.lang.fortran and read about 88tran, the totally new language with two heads, brought to you by X3J3.
yuval@taux01.UUCP (Gideon Yuval) (02/24/88)
> very well thought out. The semantics of arithmetic should > be independent of the underlying hardware, so that the same > answer is obtained on all machines for all valid operations. > (This is possible, and can be done efficiently, but the > solutions are not well known.) Indeed they are not. Can you post a pointer to these solutions? -- Gideon Yuval, +972-52-522255 (work), -2-690992 (home), yuval@taux02.nsc.com
franka@mmintl.UUCP (Frank Adams) (02/24/88)
In article <2327@umd5.umd.edu> chris@trantor.umd.edu (Chris Torek) writes: |In article <2718@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: |>Any serious effort to design a successor to C (which does not attempt to be |>upward compatible) should first consider what should be taken out and/or |>done differently. Adding new things is secondary. | |Oddly enough, I have been considering the same sort of thing myself. One of |the nicest things about the C language is what it does NOT do. The language |is small enough to learn and comprehend entirely in a short time; the list |of language oddities is not empty, but is small (most of them appear below). Agreed. |>I would also like to do away with having control statements control single |>statements. ... "if (foo) stmt1; stmt2; end;" ... |>"for <stmts| while (<exp|) next <stmts| do <stmts| end;" ... |>"loop <stmts| while (<exp|) <stmts| end;". | |I disagree with the details, I would like to see other proposals. |[may prefer 'endif' to 'end', but has doubts] I debated whether to put in 'endif', etc., or 'end' in the above, and finally opted for the shorter form. Ask me on another day and you might get a different answer. |A general aggregate constructor is necessary. Any suggestions on how to do this? |I think the following are important considerations: | | - the language should be made as small as possible, but no smaller. | | - we should assume that compilers for this language are going to | do a great deal of optimisation; in particular, they will optimise | across entire compilations, not just single files. I don't think we should *require* this. The language should still have a place for the fast and cheap compiler, which still produces reasonably good code. | - it should be relatively easy to translate `old C' to the new | language. | | - it might also be a good idea to steal liberally from C++ (which | of course steals liberally from SIMULA and others). Yes, but I would not put the object oriented stuff into D. For that, you get D++. Overloaded functions are fine, though. |My biggest worry is that if the language is too small and malleable, it |will suffer from the same problems as some of the old dynamically-extensible |languages. One solution is to make the language small but the support |`library' (including headers that define standard aggregates like C-style |arrays and strings) a `part' of the language. Definitely. Library development should go on in parallel to the language development, and whatever flexibility the language provides should be reflected in the library. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
g-rh@cca.CCA.COM (Richard Harter) (02/25/88)
In article <2731@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >In article <2327@umd5.umd.edu> chris@trantor.umd.edu (Chris Torek) writes: > >|[may prefer 'endif' to 'end', but has doubts] > >I debated whether to put in 'endif', etc., or 'end' in the above, and >finally opted for the shorter form. Ask me on another day and you might get >a different answer. Here is an alternative to endif et al. Use labels to start blocks and 'end labels' to end them. For example, if (boolean expression) foo: .... end foo else bar: .... end bar This may look odd, but it does have the advantage that it makes the block delimiting explicit. One would also need to be able to use unlabelled blocks (in macros, for example), so if (boolean expression) .... end else .... end would also fly. A disadvantage (from some viewpoints) is that, since labels now delimit control blocks, they can't be used for goto's. Sometimes, I think this might be a good idea. -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
richard@aiva.ed.ac.uk (Richard Tobin) (02/26/88)
In article <915@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes: >> >I think I would also drop the convention that 0 is a null pointer. Make >> >"null" a keyword, representing a null pointer of any type. >> This would, at one stroke, eliminate half the confusion that plagues >> comp.lang.c .... (about 1/3 :-) ) > Unless you require function prototypes to be within scope, null >will not do you much good. Ah, but if you you don't make the representation of the null pointer be the same as that of an integer (or anything else) then you can make it illegal to pass it (uncast) to a function for which there is no prototype. You can't do that with zero, unless you want to have to say (int)0 to pass an integer zero. Of course, when designing a new language you certainly could require that functions never be used unless there is a prototype (or "declaration" as one might call it) in scope. -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nss.cs.ucl.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
msb@sq.uucp (Mark Brader) (02/26/88)
> Any serious effort to design a successor to C (which does not attempt to > be upward compatible) should first consider what should be taken out and/or > done differently. Adding new things is secondary. > > The first thing I would remove is the automatic conversion of arrays to > pointers. So far I agree. > (A consequence of this change is that "a[b]" is no longer definable as > "*(a + b)". Here I disagree. We can have it both ways. Allow automatic conversion of arrays to pointers *where pointers are required*. That is, if you say "b = a;", where a is an array, you get *either* a pointer assignment or an array assignment, depending on whether b is a pointer or array variable. The present definitions of * and [] can then be happily retained. In fact, the entire present treatment of arrays can be happily retained, and thus arrays-as-first-class-objects could go into C itself -- except for one thing. Function calls. If the rule was that a prototype of the form "void fun (int a[4], int *b);" declared a function with one array and one pointer argument, then calls to this function could follow the semantics I outlined above; a call of the form fun(a,a); would pass the whole array a as the first argument, and a pointer to its start as the second argument. (Barring some form of "conformant arrays", the dimension 4 would have to match exactly.) Of course, in the present draft, that declaration declares a function with two pointer arguments. If this becomes as entrenched in the language in connection with the new prototype syntax as it is with the old function definition syntax, we will never get arrays-as-first-class-objects. This is one reason why I and others have suggested that declarations such as the above should at least cease to have their present meaning. Mark Brader "C takes the point of view SoftQuad Inc., Toronto that the programmer is always right" utzoo!sq!msb, msb@sq.com -- Michael DeCorte
henry@utzoo.uucp (Henry Spencer) (02/26/88)
> ... An undeclared variable should be an error, not an int. Um, perhaps you should learn C before you start designing D...? An undeclared variable *is* an error. > Another thing that should go is the assumption that the unit of storage is > the byte. The base unit of storage is the bit, and sizeof should return the > number of bits in the object. This enables to treat objects smaller than a > byte as first class objects. Here we have a key decision: is D to share C's emphasis on generation of efficient code? (Bearing in mind that this had a lot to do with C's success.) If so, then trying to forget that bytes exist is a serious mistake. Most machines cannot handle bits with anywhere near the efficiency with which they handle bytes; the appropriate base unit for efficient code *is* the byte. > ... In keeping with the spirit of C, we avoid > superfluous words, and keep the ones we do use short. > > With these changes, the {} statement delimiters become much less useful. I > would probably drop them, and add a "begin ... end;" construct... Please explain how avoiding superfluous words and keeping necessary ones short is consistent with changing {/} to begin/end for no particular reason. > To get even more radical -- with typedefs, enums, const declarations, and > (if we add them) inline functions, do we really need the pre-processor any > more? ... The C++ people claim that the answer is "not much", given inline functions in particular. They do still use it for some specialized problems, though. > I would omit the automatic insertion of a null byte at the end of character > constants. If you want nul terminated strings, write the nul. If you want > strings with counts, the language should not get in your way. Pray tell, how do you write a counted-string constant? I would suggest that "abc" should mean a length-3 string with any necessary terminator, regardless of what flavor of string is in use. That way you get a choice, without recoding all your string constants. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
gordan@maccs.UUCP (gordan) (02/27/88)
-> ... An undeclared variable should be an error, not an int.
-
- [various flames stating that an undeclared variable *is* an error]
Perhaps what the original poster meant by his statement was that, for
instance, the following is legal:
foo (a, b)
char a; /* b is implicitly an int */
{
...
}
(Chapter and verse: K & R, Appendix A, Section 10.1, "Any identifiers
whose type is not given are taken to be _int_.").
Of course, in the above example, 'b' is not a variable, but a formal
parameter. Still, this is a problem... I once had a hard-to-find bug
that resulted from a missing formal parameter declaration defaulting to
int. _Has_ this been changed in ANSI C?
--
I am the Lizard King "Vous cherchez Jim, Monsieur?"
and I can do anything
-- caretaker at Gordan Palameta
-- Jim Morrison Pere Lachaise mnetor!lsuc!maccs!gordan
jejones@mcrware.UUCP (James Jones) (02/27/88)
In article <1988Feb25.202237.8688@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes: > > ... An undeclared variable should be an error, not an int. > > Um, perhaps you should learn C before you start designing D...? An > undeclared variable *is* an error. Perhaps the original author was referring to letting undeclared identifiers which are followed by something that looks like an actual parameter list default to being an extern function returning int, and to the ability to elide int from declarations (which, if I rightly understand the X3J11 Draft, can still be done as long as there's *some* keyword that lets the compiler conclude that it's looking at a declaration). If that's indeed what the original author was referring to, I sincerely agree with him. (It would be nice if X3J11 deprecated it, too--which it may have, I don't recall.) James Jones
ok@quintus.UUCP (Richard A. O'Keefe) (02/27/88)
In article <24935@cca.CCA.COM>, g-rh@cca.CCA.COM (Richard Harter) writes: > Here is an alternative to endif et al. Use labels to start blocks and > 'end labels' to end them. For example, > > if (boolean expression) > foo: .... > end foo > else > bar: .... > end bar > He has just re-invented BCPL. Where C has { and }, BCPL had $( and $). The name for these was "section brackets". There was an extra hack: "tagged section brackets". If <id> looked like an identifier, $(<id> and $)<id> were tagged section brackets (each was a single token). So in BCPL this example would be TEST boolean-expression THEN $(FOO ... $)FOO ELSE $(BAR ... $)BAR PL/I has a similar feature, one can write label: DO; statements END label; /* I may have this wrong */ There is a difference, though. In BCPL, the tags on the brackets must match exactly, but in PL/I a tagged END may close any number of tagged and untagged DOs. Can anyone who has experience with using this feature suggest why it has remained rare. In particular, does anyone know why it isn't in C, given that it was in BCPL? (Not that I think it's needed.)
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/28/88)
In article <1988Feb25.202237.8688@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >Most machines cannot handle bits with anywhere near the efficiency >with which they handle bytes; the appropriate base unit for efficient code >*is* the byte. Be careful; cause and effect are circular here. I've been contacted by more than one computer architect who wanted bit addressability but had trouble convincing management to accept the slightly added expense because they would observe that such a facility could not be exploited from popular high-level languages. In fact, I have many applications for bit arrays and bit maps, and there is a severe performance penalty caused by lack of hardware support for them (and high-level language access to such support). My "short char" proposal did not REQUIRE bit addressability, but it did allow it to be exploited if the implementor decided it was wanted. (1 = sizeof(short char) <= sizeof(char).) The other main implementation would be to let a "short char" be an 8-bit byte and a normal "char" be big enough to hold an entire textual unit (typically 16 bits in Japan). Unfortunately not many committee members seem to be bit-map programmers... >Please explain how avoiding superfluous words and keeping necessary ones >short is consistent with changing {/} to begin/end for no particular reason. A better reason for a change here is the problems cause by "dangling else" and accidental ";" after the closing ")" of a while(). The idea that such clauses control a single statement (which might be a compound statement) makes C susceptible to such errors; using unique bracketing keywords would be safer. while condition do ;-separated_statements done if condition then ;-separated_statements else ;-separated_statements fi If would also be nice if such statements could return values (so ?: could be dispensed with). Better yet, adopt notation more supportive of concurrent processing, such as Dijkstra's "guarded" commands. Why not support the future?
gwyn@brl-smoke.ARPA (Doug Gwyn ) (02/28/88)
In article <1020@maccs.UUCP> gordan@maccs.UUCP (gordan) writes: >... defaulting to int. _Has_ this been changed in ANSI C? No, like other warts, since this is widely used in correctly-written (according to K&R rules) C code, and since it does not pose any true technical problems, it must continue to be tolerated. Fix it in "D".
joe@logi-dc.UUCP (Joe Dzikiewicz) (03/01/88)
Here's an operator I would like to see. It involves structure pointers...
struct a
{
struct a *a_ptr;
...
} *ptr_to_a;
...
ptr_to_a => a_ptr;
This would be equivalent to:
ptr_to_a = ptr_to_a->a_ptr;
This would not allow you to do anything you can't do anyway, but it
would reduce the needed keystrokes (and isn't that what 'C' is all
about anyway? :-).
Joe Dzikiewicz
joe@logi-dc
gamiddleton@watmath.waterloo.edu (Guy Middleton) (03/01/88)
In article <24996@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: > In article <703@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: > >In article <24935@cca.CCA.COM>, g-rh@cca.CCA.COM (Richard Harter) writes: > >> Here is an alternative to endif et al. Use labels to start blocks and > >> 'end labels' to end them.... > > >He has just re-invented BCPL. There is another thing that should be reintroduced: case ranges in switch statements. These were part of B (although they were not in BCPL): switch (x) { case <0: /* ... */ break; case 0::10: /* ... */ break; case >10: /* ... */ default: }
john@riddle.UUCP (Jonathan Leffler) (03/01/88)
In article <6306@iuvax.UUCP> cdaf@iuvax.UUCP (Charles Daffinger) writes: >I think the language you want was already designed by Nicolas Wirth: Pascal. More likely: Modula-2 After all, that was what Wirth intended to design when he designed Pascal. #include <disclaimer.h> Jonathan Leffler (john@sphinx.co.uk)
franka@mmintl.UUCP (Frank Adams) (03/01/88)
In article <24935@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: | if (boolean expression) | .... | end | else | .... | end Note that this does *not* solve the dangling else problem. That being the case, I see no reason to prefer it to the current syntax. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
franka@mmintl.UUCP (Frank Adams) (03/01/88)
In article <1988Feb25.202237.8688@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >> ... An undeclared variable should be an error, not an int. > >Um, perhaps you should learn C before you start designing D...? An >undeclared variable *is* an error. Mea culpa. The C compilers I use give warnings for undeclared functions and several other things, which I treat as errors; so sometimes I forget which ones are really errors. The point still stands as regards undeclared functions, though. >> Another thing that should go is the assumption that the unit of storage is >> the byte. The base unit of storage is the bit, and sizeof should return the >> number of bits in the object. This enables to treat objects smaller than a >> byte as first class objects. > >Here we have a key decision: is D to share C's emphasis on generation >of efficient code? Yes. >If so, then trying to forget that bytes exist is a serious >mistake. Most machines cannot handle bits with anywhere near the efficiency >with which they handle bytes; the appropriate base unit for efficient code >*is* the byte. This makes C nicely efficient on *many* machines; but there are others on which a larger size would be much better. Not every machine is byte addressable. Conversely, on those machines which *do* have bit addressing, C provides very inefficient access to it. We need to figure out how to make D efficient without regard to the addressing unit of the machine. Off-hand, I'm not sure how to do that. >> ... In keeping with the spirit of C, we avoid >> superfluous words, and keep the ones we do use short. >> >> With these changes, the {} statement delimiters become much less useful. I >> would probably drop them, and add a "begin ... end;" construct... > >Please explain how avoiding superfluous words and keeping necessary ones >short is consistent with changing {/} to begin/end for no particular reason. I was thinking that with the other changes I proposed, the compound statement would be needed only for declaring variables local to part of a function. This use is not important enough to justify allocating two special symbols to it. This overlooks the compound statement forming the body of the function. This is easily enough dealt with by making the function syntax be: type declarator declarations statements end ; instead of type declarator { declarations statements } One possible use for the braces would be as type parentheses, so one could write: {int *} a, b; to make both a and b pointers to int. I think using this for casts would improve readability as well. (That is, replace the parentheses around the cast type with braces.) This is an off-the-cuff idea, there may be better ones. >> do we really need the pre-processor any more? ... > >The C++ people claim that the answer is "not much", given inline functions >in particular. They do still use it for some specialized problems, though. Overall, the preprocessor seems to be used as a way to hack prototypes for the next extension to the language. C++ people tend to use it for parameterized types, early C used it for consts and enums, etc. This may be an argument for keeping it. >> I would omit the automatic insertion of a null byte at the end of character >> constants. If you want nul terminated strings, write the nul. If you want >> strings with counts, the language should not get in your way. > >Pray tell, how do you write a counted-string constant? struct string {char * data; int size}; char dummy[] = "This is my string." struct string s = {&dummy, sizeof(dummy)}; If you want the length immediately preceding the string, you need new syntax and/or the pre-processor to avoid writing the string twice. >I would suggest that "abc" should mean a length-3 string with any necessary >terminator, regardless of what flavor of string is in use. That way you get >a choice, without recoding all your string constants. And how do you specify what flavor of string is "is use?". -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
decot@hpisod2.HP.COM (Dave Decot) (03/01/88)
Array first-class-ness and aggregate constants could be easily provided within C (not that I want to discourage D-zigners; it's a meritorious idea). The basic ideas are that "a[]" is an array lvalue, and that aggregate constants are natively typeless and must always be either cast or assigned to the appropriate type. Two examples follow. (Watch out for the extensions to printf(3S) and scanf(3S) for array handling.) I will explain any of this if desired. EXAMPLE 1 int thing(i, a, b)[2] int i, a[2], b[2]; { int val[2]; val[0] = a[i] - b[0]; val[1] = a[i] - b[1]; return (val[]); } main() { typedef int PAIR[2]; char *message = "END-OF-EXAMPLE"; PAIR p1, p2, p3[2]; p1[] = {2, -3}; printf(p1: "%(2)4d\n", p1); p2[] = {1, 7}; printf("p2: %(2)4d\n\n", p2); p3[0][] = thing(0, p1[], p2[]); p3[1][] = thing(1, p1[], (PAIR) {1, 7}); printf("p3: %(2; )(2, )d\n\n", p3); printf("%(* )c\n", strlen(message), message); printf("%(*:-])c\n", strlen(message)*2/3, (char *)NULL); } prints p1: 2 -3 p2: 1 7 p3: 1, -5; -4, -10 E N D - O F - E X A M P L E :-]:-]:-]:-]:-]:-]:-]:-]:-] ANOTHER EXAMPLE main() { int array[10][10]; int array2[100][10] = {0}; /* fills entire auto array with 0s */ int row; scanf("%(10 )(10 )d", array); /* reads free-format 10x10 array */ /* copy array into top 10 rows of array2 */ for (row = 0; row < 10; row++) array2[row][] = (int [100]) array[row][]; /* cast is not needed */ reduce( (int [100][100]) array2[], 10); /* this cast is required */ for (row = 0; row < 10; row++) /* copy the rows back */ array[row][] = array2[row][]; printf("%(10\n)(10 )6d\n", array); /* display square array */ } reduce(a, n) int a[100][100]; int n; { /* ... */ }
wes@obie.UUCP (Barnacle Wes) (03/01/88)
Frank, if you want to write your programs in Ada, write them in Ada. Don't try to re-write a C compiler to accept Ada programs. In fact, you should re-post this message in comp.lang.ada, I think you'd find a more receptive audience there. Since the name Ada has already been used, and your language is sufficiently different from C to NOT name it D, perhaps you could call it "DoD". But that's been used, too, hasn't it? (-: :-) (-: :-) (-: :-) -- /\ - "Against Stupidity, - {backbones}! /\/\ . /\ - The Gods Themselves - utah-cs!utah-gr! / \/ \/\/ \ - Contend in Vain." - uplherc!sp7040! / U i n T e c h \ - Schiller - obie!wes
dsill@NSWC-OAS.arpa (Dave Sill) (03/02/88)
In article <225800007@uxe.cso.uiuc.edu> mcdonald@uxe.cso.uiuc.EDU writes: >I find it hard to believe that a successor to C is needed or would be >appreciated. Yes, C is adequate for most of today's needs. But it does have its problems and weaknesses. If we want to have a language to take its place tomorrow, we had better start thinking about it today, though. >I come to this as a former 100% Fortran (and assembler) >programmer who now uses C about 80 % of the time. C does have a few, >minor defects (for instance, I will never , ever understand the syntax >of declarations; I have had a guru make up a huge chart listing dozens of >them, which I carry in my wallet.) So does every other language. To varying degrees. Hopefully D will learn from C, and at least not repeat the same mistakes. >C does >one thing extremely well: convert the heart of the machine operations of >a byte-addressible, conventional processor (i.e. the PDP11) into a nice >higher language. Certainly an appropriate behavior for a systems programming language designed in the early seventies. But D should be targeted to a more general purpose, as C is being used today. Also, D should be more adaptable to unconventional processors than C is. E.g., it should be more suitable for parallel processing environments. >It is pleasantly compact, and very full of nice >shortcuts (e.g. "string"[i] ). If you dislike C , try other languages: >Fortran, Pascal, Ada ,Modula 2. Me, well , I like C and Fortran and loathe >the rest. D would not be for people who dislike C. It would be for people who like C but find it lacking by today's standards in certain areas. >But if a new language is to be designed, and done really well, it >won't be done by committee. For the perfect example look in comp.lang.fortran >and read about 88tran, the totally new language with two heads, brought >to you by X3J3. We aren't designing D here. We are pointing out those things lacking in C that we'd like to see done right in a currently hypothetical successor. Of course if somebody wanted to digest our discussions, design a language based on them, implement a compiler (perhaps based on GNU C or C++), call it D, and distribute it freely, I wouldn't complain. ========= The opinions expressed above are mine. "The limits of my language mean the limits of my world." -- Ludwig Wittgenstein
dsill@NSWC-OAS.arpa (Dave Sill) (03/02/88)
(Not really a C issue) Am I the only person in the world that thinks it's time to scrap ASCII? Look at the contortions we have to go through in C because there aren't really enough characters for the operators needed. Look at the messes we get into under the UNIX shells with quote characters, delimiters, et cetera. Wouldn't it be simpler if punctuation was punctuation and metacharacters were metacharacters and there was no overlap between the two? APL, of course, solved this problem by inventing its own character set. Unfortunately, it was nonstandard and there was almost no equipment that used that character set. The time is ripe for a more flexible "Code for Information Interchange". How many more years/decades will we be forced to make do with a lousy 95 symbols: all predefined, most vastly overloaded? C would have been much more usable language if it hadn't had to have been mapped to ASCII. D could be the best of C and APL if a larger character set was available. I know, I know, the cost of such a change would be phenomonal. Even deciding on a new standard will be hard/expensive/time-consuming, but it's *got* to be done sooner or later. (Not until we've lived with several incompatible proprietary systems for a while, though.) I just needed to get that off my chest, sorry if I bothered you. ========= The opinions expressed above are mine. "There is very little importance in instruction sets." -- Ted Nelson "There is very much importance in character sets." -- Me
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/02/88)
In article <12059@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >The time is ripe for a more flexible "Code for Information >Interchange". How many more years/decades will we be forced to make >do with a lousy 95 symbols: all predefined, most vastly overloaded? ISO extended the character set several years ago. It has also been extended (in more than one way) to accommodate Kanji characters. C source can be in EBCDIC (for example); it seems inappropriate to require either a specific character code "standard", or an even larger set of characters than it already uses, given the amount of trouble with this we've already had.
karl@haddock.ISC.COM (Karl Heuer) (03/02/88)
>In article <1988Feb25.202237.8688@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >>Most machines cannot handle bits with anywhere near the efficiency >>with which they handle bytes; the appropriate base unit for efficient code >>*is* the byte. "Word-addressible cannot handle bytes with anywhere near the efficiency with which they handle words; the appropriate base unit for efficient code is the word." Right? On a word-addressible machine, there is a perceived need to address objects smaller than one word; hence most C compilers give you access to individual bytes via "char". (There may be some that define char as a machine word, but I'm not familiar with any.) Similarly, on byte-addressible machines there is a (less) perceived need to address objects smaller than one byte. If sizeof were measured in bits (the original statement in this thread, I believe), then (a) no functionality would be lost, because you get the number of char-sized bytes by using sizeof(thing)/sizeof(char); and (b) it becomes possible to add a datatype "bit" with sizeof(bit)==1. Code that doesn't use it would still be just as efficient as it used to be. Code that does use it on a bit-addressible machine would have access to the entire address space. And code that uses it on a byte- or word-addressible machine may have to use goofy pointers, just like (char *) on a word-addressible machine. (Presumably the author of such code is aware of the space-time tradeoffs.) In article <7359@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >My "short char" proposal did not REQUIRE bit addressability, but it did >allow it to be exploited if the implementor decided it was wanted. >(1 = sizeof(short char) <= sizeof(char).) This is a less radical proposal, which would be consistent with C. >The other main implementation would be to let a "short char" be an 8-bit byte >and a normal "char" be big enough to hold an entire textual unit (typically >16 bits in Japan). I see this as a different problem, which is better solved by "long char". For example, a Japanese system on a bit-addressible machine should be able to use both features: 1-bit short char, 8-bit char, 16-bit long char. >>Please explain how avoiding superfluous words and keeping necessary ones >>short is consistent with changing {/} to begin/end for no particular reason. > >A better reason for a change here is the problems cause by "dangling else" >and accidental ";" after the closing ")" of a while(). A better change would be to leave the punctuation alone, and but make the braces required even for a null- or single-statement body. In other words, change the syntax to read "compound-statement" instead of "statement". >If would also be nice if such statements could return values (so ?: could >be dispensed with). Yes, let's make *all* statements return values (more precisely, remove the distinction between expressions and statements). Then there's no need for the distinction between ?: vs. if-else, nor () vs. {}, nor the comma operator vs. semicolon. (The semicolons in the "for" statement are a minor nuisance, but no worse than non-operator commas. "for ((i=0; j=N); i<N; (++i; --j))" is parsable.) Statements that have no obvious value (while; elseless if) could be void expressions. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
karl@haddock.ISC.COM (Karl Heuer) (03/02/88)
In article <7362@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <1020@maccs.UUCP> gordan@maccs.UUCP (gordan) writes: >>... defaulting to int. _Has_ this been changed in ANSI C? > >No, like other warts, since this is widely used in correctly-written >(according to K&R rules) C code, and since it does not pose any true >technical problems, it must continue to be tolerated. Fix it in "D". In a similar vein, using "int" (or the "implied int" you get by leaving out the type) for a function which returns no value should disappear. Hey Doug, couldn't this be deprecated on the same grounds as old-style function declarations? A new syntax ("void") has been standardized which does the job better, and the old syntax makes it harder to diagnose certain bugs. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
dsill@NSWC-OAS.arpa (Dave Sill) (03/02/88)
>In article <12059@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >>The time is ripe for a more flexible "Code for Information >>Interchange". How many more years/decades will we be forced to make >>do with a lousy 95 symbols: all predefined, most vastly overloaded? > >ISO extended the character set several years ago. It has also been >extended (in more than one way) to accommodate Kanji characters. Yes, I've read the ISO standards you refer to (ISO 646, ISO 2022, ISO 2375, ISO 6429), they're sitting on my desk right now. ISO 646 is like ASCII, except that it allows the construction of "composite graphic characters". This is great, the sequence "=<CR>/", for example, could be displayed as a "not-equal" symbol. Unfortunately, ISO 646 doesn't say what these composite characters look like, so it could be displayed as a ham sandwich, or as an equals sign with the first character of the line replaced with a /. Real useful. ISO 2022 covers extensions to ISO 646 using alternate graphical character sets, escape sequences, and 8-bit codes. But it says nothing about what a given pattern looks like in a given character set. It does, however, maintain interchangeability between 7-bit and 8-bit standard and extended environments, which is A Good Thing. ISO 2375 is a procedure for registering ISO 2022 escape sequences. This seems like a step in the right direction. Too bad they don't have such a procedure for the alternate graphical character sets. ISO 6429 contains control functions for display devices. It's interesting to note that although this standard has been available since '83, only one vendor that I'm aware of claims conformance (Canon, in their laser printers. If there are others you're aware of, I'd like to know). Not exactly overwhelming acceptance. The real problem, though, is not so much in the code itself as it is in the display devices, terminals, keyboards, et cetera, that are used to enter and display these characters. Even if the ISO standards defined the code for a right-pointing-arrow, what key or key- combination would have to be used to enter one? How could it be displayed? >C source can be in EBCDIC (for example); it seems inappropriate to >require either a specific character code "standard", So you're saying we can't extend the set of graphical characters we use in languages because someone might not have the characters available? What about trigraphs, or a similar mechanism? >or an even >larger set of characters than it already uses, given the amount of >trouble with this we've already had. The trouble is not that we have too many characters available, it's that we have too few! For example, if we had a left-pointing-arrow character that could be used for assignment, the whole == versus = problem would not exist. ========= The opinions expressed above are mine. "The limits of my language mean the limits of my world." -- Ludwig Wittgenstein
ned@ghostwheel.UUCP (Ned Nowotny) (03/03/88)
Followup -To: In discussing various successor languages, perhaps the following naming conventions would be in order: C - The language we all know and love (or loath, as the case may be). C++ - The well-know C-like language with object-oriented extensions. D - The natural C-like successor language. D++ - The natural C++-like successor language. C+C - C with extensions for numerical analysis. C[N] - C with extensions for vector architectures and optimization. (C) - Functional C. !C - A pseudo-C with a high degree of structuring and strong typing. &&C++ - ANSI C. -- Ned Nowotny (ned@ghostwheel.aca.mcc.com.UUCP)
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/03/88)
In article <2809@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >If sizeof were measured in bits ... >In article <7359@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >>My "short char" proposal did not REQUIRE bit addressability, but it did >>allow it to be exploited if the implementor decided it was wanted. >>(1 = sizeof(short char) <= sizeof(char).) The reason for not insisting on sizeof() being in bits was that it would add at least three bits to the required size_t for a byte-oriented implementation, with no particular gain in that case. >Yes, let's make *all* statements return values ... I once designed a language like this for a special purpose. It worked, but you need to figure out what to do about declarations. What values should they return?
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/03/88)
In article <2810@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >Hey Doug, couldn't this be deprecated on the same grounds as old-style >function declarations? It's been suggested before, but hey, send it in. Maybe you can think of more persuasive arguments.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/03/88)
In article <12073@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >The trouble is not that we have too many characters available, it's >that we have too few! For example, if we had a left-pointing-arrow >character that could be used for assignment, the whole == versus = >problem would not exist. My point is that it does no good to introduce a language that uses funny APL-like symbols, when the vast majority of existing and near-future terminals and printers won't support the symbols. (I doubt that many even support the full set already registered with ISO.) What you end up with are a bunch of kludges, like the proposed ANSI C trigraphs, that everybody ends up having to cope with. By limiting the language symbols to those commonly available, you make programs much more readable in practice. It isn't clear to me that funny APL-like symbols are preferable to short keywords (for example). Note that even the mathematicians are starting to use such notations in preference to inventing mystical symbols, especially in category theory.
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/03/88)
In article <2737@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >We need to figure out how to make D efficient without regard to the >addressing unit of the machine. Off-hand, I'm not sure how to do that. Obviously, you let the compiler take care of allocating suitable sizes. For it to do this, the programmer needs to specify something about the intended usage of the variable, such as is done with enumeration types, Booleans, and subscript ranges in various languages.
flaps@dgp.toronto.edu (Alan J Rosenthal) (03/03/88)
In article <105@logi-dc.UUCP> joe@logi-dc.UUCP (Joe Dzikiewicz) writes: > ptr_to_a => a_ptr; > >This would be equivalent to: > > ptr_to_a = ptr_to_a->a_ptr; the correct operator is probably '->=' rather than '=>', by analogy with '+=' and friends. (this wouldn't even change the meaning of "a-->=b"...) -- If you had eternal life, would you be able to say all the integers?
franka@mmintl.UUCP (Frank Adams) (03/03/88)
In article <264@aiva.ed.ac.uk> richard@uk.ac.ed.aiva (Richard Tobin) writes: |Of course, when designing a new language you certainly could require |that functions never be used unless there is a prototype (or |"declaration" as one might call it) in scope. I certainly *would* require this. -- Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Ashton-Tate 52 Oakland Ave North E. Hartford, CT 06108
ok@quintus.UUCP (Richard A. O'Keefe) (03/03/88)
In article <12059@brl-adm.ARPA>, dsill@NSWC-OAS.arpa (Dave Sill) writes: > Am I the only person in the world that thinks it's time to scrap ASCII? > The time is ripe for a more flexible "Code for Information > Interchange". How many more years/decades will we be forced to make > do with a lousy 95 symbols: all predefined, most vastly overloaded? > Even deciding on a new standard will be hard/expensive/time-consuming, > but it's *got* to be done sooner or later. It has already been done. DIS 8859/1 (it may be a full ISO standard by now) is an 8-bit extension of ASCII. DEC already have it (almost) and SUN are moving in that direction. At long last we have a *standard* character set where C-with-a-ring-around-it is an actual character. The System V Interface Definition hints that 8-bit characters will be an official part of some future System V.
g-rh@cca.CCA.COM (Richard Harter) (03/03/88)
In article <2736@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >In article <24935@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: || if (boolean expression) || .... || end || else || .... || end | |Note that this does *not* solve the dangling else problem. That being the |case, I see no reason to prefer it to the current syntax. I wasn't suggesting it as a resolution of the dangling else problem, because, as you note, it isn't whether or not one has labels. It struck me as an idea that might have some value -- and it might if the compiler pro- duced a listing that labelled each line with the block that was part of. I am now persuaded that the idea has no particular merit. If one is really concerned about the dangling else problem there is a very simple solution -- use different keywords for two sided if's and one sided if's. For example, the presence of a 'then' keyword guarantees an 'else' and its absence guarantees the lack of an 'else'. E.g. if (e1) then if (e2) A; else B; <---- this pairs with the first if if (e1) if (e2) then A; else B; <---- this pairs with the second if if (e1) if (e2) A; else B; <---- this is a syntax error Another cure is to always require that an 'else' statement be present, even it if it is null. Personally, I am inclined to feel that all of the cures (including endif) are worse than the disease. -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
dsill@NSWC-OAS.arpa (Dave Sill) (03/03/88)
(I'm risking beating a dead horse here, but I *do* want to make sure it's dead.) In article <7399@brl-smoke.ARPA> Doug Gwyn <gwyn@brl-smoke.arpa> writes: >My point is that it does no good to introduce a language that uses >funny APL-like symbols, when the vast majority of existing and >near-future terminals and printers won't support the symbols. I totally agree. It's the latter I lament. >It isn't clear to me that funny APL-like symbols are preferable to >short keywords (for example). It isn't clear to some people that icons are preferable to filenames, either. However, I think the majority prefers mnemonic symbols for operators. X <- Y is more mnemonic for assignment than X = Y. Nobody would really prefer the <- digraph to a real left-arrow character, though. >Note that even the mathematicians are >starting to use such notations in preference to inventing mystical >symbols, especially in category theory. I don't know diddly about category theory. But I do know that some day, maybe 10 years from now, maybe 50 years from now, we will finally have to admit that the typewriter keyboard designed at the turn of the century is simply no longer adequate. As Wittgenstein points out, the limits of our language (or our alphabet) limit our ability to conceptualize and communicate clearly. It's not good enough to say that we have an unlimited number of combinations of characters available so we're really not limited. That's the equivalent of saying we only need a 5000 (or whatever) word vocabulary since all others words can be defined using the fixed vocabulary. ========= The opinions expressed above are mine. "The limits of my language mean the limits of my world." -- Ludwig Wittgenstein
henry@utzoo.uucp (Henry Spencer) (03/04/88)
> >Most machines cannot handle bits with anywhere near the efficiency > >with which they handle bytes... > > Be careful; cause and effect are circular here. I've been contacted by > more than one computer architect who wanted bit addressability but had > trouble convincing management to accept the slightly added expense because > they would observe that such a facility could not be exploited from popular > high-level languages... I once had the opportunity to ask Bill Wulf what he thought of bit-oriented machines; his answer was "I wish they weren't so damned slow". I'm afraid I haven't seen anything since that invalidates that assessment. There is something to be said for providing bit addressability, but one must realize that actually exploiting it will be slow and that there will still be a large payoff for trying to work on byte or word boundaries whenever possible. Also, designing D so it will run real well on our hypothetical dream machine is probably not a good idea. > >Please explain how avoiding superfluous words and keeping necessary ones > >short is consistent with changing {/} to begin/end for no particular reason. > > A better reason for a change here is the problems cause by "dangling else" You misunderstood here, Doug. I have no objection to self-bracketing control constructs, in fact I quite like them. What I was objecting to was retaining an explicit bracketing construct but changing its spelling. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
henry@utzoo.uucp (Henry Spencer) (03/04/88)
>>Most machines cannot handle bits with anywhere near the efficiency >>with which they handle bytes; the appropriate base unit for efficient code >>*is* the byte. > >"Word-addressible cannot handle bytes with anywhere near the efficiency >with which they handle words; the appropriate base unit for efficient code >is the word." Right? See Bliss and BCPL, which were built for word-addressed machines. The fact is that C assumes a byte-addressible machine. It has been ported to word- addressed machines; this involves problems, and C programs are sometimes quite inefficient on such machines, but it does work. Basing C on bytes was probably the right thing to do (even ignoring the fact that portability originally wasn't a big consideration), because most modern machines support them well. I question the wisdom of basing a new portable general-purpose language on the bit, which very few existing machines support well. -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
henry@utzoo.uucp (Henry Spencer) (03/04/88)
> >I would suggest that "abc" should mean a length-3 string with any necessary > >terminator, regardless of what flavor of string is in use... > > And how do you specify what flavor of string is "is use?". Pick a way. I can think of several. The point is that the compiler, not the user, should be charged with translating a string constant into the correct internal representation. It can generate a count just as easily as it can generate a trailing NUL, and either way this is much better than making the programmer do it. -- 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/04/88)
In article <7395@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn) writes: >In article <2809@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >>Yes, let's make *all* statements return values ... > >I once designed a language like this for a special purpose. It worked, but >you need to figure out what to do about declarations. What values should >they return? When in doubt, make it a void expression. Personally, I think even strcpy() should be void. Alternately, if only one object can be declared per statement, it could return that object (if it was initialized) or its address (assuming it has one). Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
ok@quintus.UUCP (Richard A. O'Keefe) (03/04/88)
In article <25203@cca.CCA.COM>, g-rh@cca.CCA.COM (Richard Harter) writes: > If one is really concerned about the dangling else problem there > is a very simple solution -- use different keywords for two sided if's and > one sided if's. BCPL did this: TEST is the two-armed version, and IF the one-armed one. There was presumably a reason why C did not inherit this feature; does anyone know what the reason was?
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/04/88)
In article <1988Mar3.182645.703@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes: >I once had the opportunity to ask Bill Wulf what he thought of bit-oriented >machines; his answer was "I wish they weren't so damned slow". I'm afraid >I haven't seen anything since that invalidates that assessment. There is >something to be said for providing bit addressability, but one must realize >that actually exploiting it will be slow and that there will still be a >large payoff for trying to work on byte or word boundaries whenever possible. Bit-addressable architectures need not be slow; you could apply the same line of reasoning to "prove" that byte-addressability makes a machine too slow, but of course they aren't necessarily slow. The main trick to is handle most operations at a large alignment and revert to bit accesses only when called for, in which case they will certainly be faster than the corresponding code on an equivalent non bit-addressable architecture.
msb@sq.uucp (Mark Brader) (03/05/88)
Dave Decot (decot@hpisod2.HP.COM) writes: > Array first-class-ness and aggregate constants could be easily provided > within C (not that I want to discourage D-zigners; it's a meritorious idea). > > The basic ideas are that "a[]" is an array lvalue, and that aggregate > constants are natively typeless and must always be either cast or assigned > to the appropriate type. Two examples follow. The a[] syntax isn't needed, any more than you need a special syntax for struct assignment. Dave's first example revised: int thing(i, a, b)[2] int i, a[2], b[2]; { int val[2]; ... return val; } Since the type to be returned is int[2], the value "val" is left as an int[2] type item and not converted to int *. The one thing that would have to change, of course, is the present rule that the formal parameter declaration int a[2] means int *a. As I have said before, this rule change could be introduced into the language along with prototype syntax. Mark Brader, utzoo!sq!msb, msb@sq.com C unions never strike!
g-rh@cca.CCA.COM (Richard Harter) (03/05/88)
Here is another feature for D whose absence in C has been irksome to
me -- I would like to be able to return several items from a function.
The problem is that arguments to C are passed by copying the value --
this is loverly since it means that my function can't munge the stuff
passed to it. But how do I get stuff back. I can pass one thing back
via the return statement. To pass more than one thing I have to play
games. Things which are returned need a mechanism equivalent to pass
by address.
An ancient and venerable way to handle this is to have 'in', 'out', and
'update' qualifiers for arguments. I have seen this used in several
languages, and my observation is that it doesn't work; people end up
bypassing the mechanism.
The following example is illustrative syntax only:
[int *,int] foobar();
....
[ptr,flag] = foobar(arg)
int arg;
{
int *a, *b;
....
return [a,1];
....
return [b,0];
}
--
In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
Richard Harter, SMDS Inc.
daveb@laidbak.UUCP (Dave Burton) (03/06/88)
In article <25284@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: >Here is another feature for D whose absence in C has been irksome to >me -- I would like to be able to return several items from a function. >... But how do I get stuff back. >... Things which are returned need a mechanism equivalent to pass >by address. Please don't design D until you understand C. C has had pass by reference for a very long time (since its inception?). The following useless code illustrates: int flag, foobar(); x = foobar(&flag); ... int foobar(arg) int *arg; { *arg = 1; return 0; } Now, what could be simpler? -- --------------------"Well, it looked good when I wrote it"--------------------- Verbal: Dave Burton Net: ...!ihnp4!laidbak!daveb V-MAIL: (312) 505-9100 x325 USSnail: 1901 N. Naper Blvd. #include <disclaimer.h> Naperville, IL 60540
cik@l.cc.purdue.edu (Herman Rubin) (03/06/88)
In article <25284@cca.CCA.COM>, g-rh@cca.CCA.COM (Richard Harter) writes: ........ > But how do I get stuff back. I can pass one thing back > via the return statement. To pass more than one thing I have to play > games. Things which are returned need a mechanism equivalent to pass > by address. No, what is needed is to abandon the mistaken notion that a function returns a single result. From day one, lists should have been allowed to the left of the replacement sign--this is not just for functions, but even for direct operators. For example, the infamous frexp function in C should not have the syntax y = frexp(x,&n); but y,n = frexp(x); This would, for example, allow n to be in a register, which is probably where it should be anyhow. Another example would be to have q,r = a///b; where the quotient and remainder are simultaneously produced. Possibly if that were in the language, we would not find the operation disappearing from hardware. ...... > > The following example is illustrative syntax only: > > [int *,int] foobar(); > .... > [ptr,flag] = foobar(arg) > int arg; > { > int *a, *b; > .... > return [a,1]; > .... > return [b,0]; > } I would drop the brackets, but otherwise the notation is reasonable. Another thing is to allow the return value to be stored _before_ the return statement. It may be desirable to do other computations after computing the value, especially for functions with side effects, such as random number procedures. -- 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
throopw@xyzzy.UUCP (Wayne A. Throop) (03/07/88)
> gwyn@brl-smoke.ARPA (Doug Gwyn ) >> henry@utzoo.uucp (Henry Spencer) >>Bill Wulf [... states ...] of bit-oriented >>machines [...] "I wish they weren't so damned slow". I'm afraid >>I haven't seen anything since that invalidates that assessment. I have. > Bit-addressable architectures need not be slow; you could apply the same line > of reasoning to "prove" that byte-addressability makes a machine too slow, Exactly so. The only problem that bit addressability (as opposed to byte addressability) brings to the game is an eight-times smaller address space for a given number of bits. But nobody claims that the four-or-eight-times smaller address space of byte-granular vs word-granular architectures means word-granular architectures are the only viable ones, nor that byte-granular ones are noticeably slower. And having participated in developing language tools for a bit-granular addressed architecture, I'll add that bit granularity eliminates a whole raft of inefficent and ugly kludgerey associated with simulating the bit granularity needed in so many places. I'm convinced it's worth it. But perhaps I'm misunderstanding what Henry means by "bit-oriented"... I'm arguing only for bit-granular addressing. -- IBM manuals are written by little old ladies in Poughkeepsie who are instructed to say nothing specific. --- R. T. Lillington -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
decot@hpisod2.HP.COM (Dave Decot) (03/07/88)
> Dave Decot (decot@hpisod2.HP.COM) writes: > > The basic ideas are that "a[]" is an array lvalue... > > The a[] syntax isn't needed... > > int thing(i, a, b)[2] > int i, a[2], b[2]; > { > int val[2]; > ... > return val; > } > > Since the type to be returned is int[2], the value "val" is left as an > int[2] type item and not converted to int *. This sounds great; I like the idea that it's possible for the intuitive array name to refer to the whole array. However, the meaning of function calls containing array names would depend so heavily on the declarations of the arguments, and the fact that it is unworkable without ANSI strong typing, makes me still lean toward having an explicit way to request what I want to happen. Perhaps this would be desirable for no other reason than to allow cc or lint to catch misuses. For instance, I'm not sure how to tell varargs functions whether I'm talking about an array pointer or a whole array if the name might mean either. Dave Decot hpda!decot
mrd@sun.soe.clarkson.edu (Michael R. DeCorte) (03/07/88)
Posting-Front-End: GNU Emacs 18.47.2 of Thu Dec 10 1987 on sun.mcs.clarkson.edu (berkeley-unix)
In article <700@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
No, what is needed is to abandon the mistaken notion that a function
returns a single result. From day one, lists should have been allowed
to the left of the replacement sign--this is not just for functions,
but even for direct operators. For example, the infamous frexp function
in C should not have the syntax
y = frexp(x,&n);
but
y,n = frexp(x);
Isetl has something of this sort. In Isetl [1,2,3] is a tuple and
if you say
[a,b] := [b,a];
you have a swap routine.
[a,b,c] := f();
and f() returns [1,2,3] you will get the assignments that you want.
Views expressed here do not represent Clarkson University or any part of it.
Michael DeCorte // (315)268-3704 // P.O. Box 652, Potsdam, NY 13676
Internet mrd@clutx.clarkson.edu // BIX DMichael
Bitnet mrd@clutx.bitnet // Compuserve 72220,3724
ok@quintus.UUCP (Richard A. O'Keefe) (03/08/88)
In article <700@l.cc.purdue.edu>, cik@l.cc.purdue.edu (Herman Rubin) writes: > No, what is needed is to abandon the mistaken notion that a function > returns a single result. From day one, lists should have been allowed > to the left of the replacement sign--this is not just for functions, > but even for direct operators. MESA does this. Every function in MESA takes a record as argument and delivers a record as result. Since MESA has keyword constructors for records, this magically yields keyword inputs _and_ keyword results.
mark@applix.UUCP (Mark Fox) (03/08/88)
In article <670@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes:
+++henry@utzoo.uucp (Henry Spencer)
+++Bill Wulf [... states ...] of bit-oriented
+++machines [...] "I wish they weren't so damned slow". I'm afraid
+++I haven't seen anything since that invalidates that assessment.
+I have.
+Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
Come on Wayne, FHP was fast?
--
Mark Fox
Applix Inc., 112 Turnpike Road, Westboro, MA 01581, (617) 870-0300
uucp: {ames,rutgers}!harvard!m2c!applix!mark
g-rh@cca.CCA.COM (Richard Harter) (03/08/88)
In article <1354@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes: >In article <25284@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: >>Here is another feature for D whose absence in C has been irksome to >>me -- I would like to be able to return several items from a function. >>... But how do I get stuff back. >>... Things which are returned need a mechanism equivalent to pass >>by address. >Please don't design D until you understand C. Er, Dave, may I suggest it is inadvisable to make remarks such as "Please don't design D until you understand C". I am not a C guru; I read with respect the comments of people such as Chris Torek and Henry Spencer. I don't need to be a complete expert in the language. None-the-less I have been programming for 27 years, writing C for six of those years, have written ~100,000 lines of C, and have dealt with the vagaries of C implementations on a variety of operating systems. >C has had pass by reference for a very long time (since its inception?). Actually C has never had pass by reference -- what it has had is a facility for simulating call by reference, which is a somewhat different matter. >The following useless code illustrates: > > int flag, foobar(); > x = foobar(&flag); > ... > int foobar(arg) > int *arg; > { > *arg = 1; > return 0; > } > >Now, what could be simpler? And this is what I was alluding to when I referred to playing games with pointers. In the call statement you have to add an &; in each reference in the routine you add a *. You have to also select one item as a distinguished item which is returned by the function among those that are returned. Of course you can do this -- you don't have much option about it. But it is a kludge, and it is prone to error. Throughout the code you "mean" flag, but sometimes you write &flag, and sometimes you write *flag, depending on where you are. Fortunately, the effects of ommitting an & or a * are so drastic that typographic bugs of this sort are caught immediately. But I've seen it come up a number of times. A more subtle point is that there is a difference in semantics between returning a list and passing things through the calling sequence. A returned value is private unless it is explictly declared as a global; an item passed through a calling sequence may be a global and the called routine does not know this. For example, FILE 1: int x; foo () { .... x = 2; baz(x,&x); } FILE 2: extern x; baz(in,out) int in, *out; { *out = 1; ... *out = *out + x; } is quite different from the same code where baz is a function returning a value which is declared internally. Call by reference is subject to unintended aliasing, whether it be real call by reference or simulated call by reference. Finally, there is one other annoying consequence of the pointer hack. You can run into pointer to 0 dereferencing problems if you aren't careful. You shouldn't, but you can. -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
jbn@glacier.STANFORD.EDU (John B. Nagle) (03/09/88)
If you want multiple values from functions, look at Mesa, which offers an efficient approach. In Mesa, all functions effectively take one argument and return one result, but both are structures. The normal function call syntax is treated as a structure constructor which builds a structure out of the arguments, then passes the structure as a unit. The structure is usually built on the stack, and thus this is equivalent in an implementation sense to the passing of parameters on the stack. In turn, a function returns a result which is a structure. The space for that structure is allocated by the caller, on the stack, and its address is passed to the function, which then fills it in. This approach seems to work.
rrr@naucse.UUCP (Bob Rose ) (03/09/88)
In article <1354@laidbak.UUCP>, daveb@laidbak.UUCP (Dave Burton) writes: > In article <25284@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: > >I would like to be able to return several items from a function. > Please don't design D until you understand C. > C has had pass by reference for a very long time (since its inception?). > The following useless code illustrates: > > int flag, foobar(); > x = foobar(&flag); > ... > int foobar(arg) int *arg; > {*arg = 1;return 0;} > > Now, what could be simpler? Easy [int, int] foobar() /* prototype */ .... [x, flag] = foobar(); .... [int, int] foobar() { return [0, 1]; } Yes I admit this looks a bit strange but look at some of the things we can do with multi assignments [x, y] = [y, x] /* swap */ The only question is should we be allowed to index this stuff so if (([x, flag] = foobar())[1]) { /* the flag was true */ .... } Anyone for comp.lang.d Robert R. Rose Northern Arizona University, Box 15600 Flagstaff, AZ 86011 .....!ihnp4!arizona!naucse!rrr
cik@l.cc.purdue.edu (Herman Rubin) (03/09/88)
In article <17351@glacier.STANFORD.EDU>, jbn@glacier.STANFORD.EDU (John B. Nagle) writes: > > If you want multiple values from functions, look at Mesa, which offers > an efficient approach. In Mesa, all functions effectively take one argument > and return one result, but both are structures. The normal function call > syntax is treated as a structure constructor which builds a structure out > of the arguments, then passes the structure as a unit. The structure is usually > built on the stack, and thus this is equivalent in an implementation sense > to the passing of parameters on the stack. In turn, a function returns a > result which is a structure. The space for that structure is allocated by > the caller, on the stack, and its address is passed to the function, which > then fills it in. > > This approach seems to work. There are two problems with this. While using stacks may be easy to program, it involves lots of loads and stores. I know of at least one machine on which the normal subroutine call and return do not use stacks. Furthermore, if the called routine may make additional calls, it may be necessary to use a separate return stack, and this may require each such subroutine to maintain its own return stack. In some cases this should be the way to do things, but not always. Another problem comes with inline functions. I believe that many function calls, if not most, should be inline. In this case, I think the result should go to its destination at the time produced. If the destinations involve registers or register indirects, the expression of the algorithm must take the busy set of registers into account. This admittedly makes coding difficult, and is one reason why I believe DNA can optimize better than silicon. (The two should be used together, but I do not know of any compiler which allows the programmer to even give it a hint as to how to optimize, let alone improve the resulting product.) -- 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
twb@hoqax.UUCP (BEATTIE) (03/09/88)
I have been trying to ignore this D discussion but it seems to be going on forever. Why is this D discussion in the C group?
daveb@laidbak.UUCP (Dave Burton) (03/10/88)
Sorry if this is a repost. The first one escaped while I wasn't looking :-). -- (how fast is a cancel, anyway?) -- In article <25387@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: |In article <1354@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes: |> int flag, foobar(); |> x = foobar(&flag); |> ... |> int foobar(arg) int *arg; |> { *arg = 1; return 0; } |And this is what I was alluding to when I referred to playing games with |pointers. In the call statement you have to add an &; in each reference |in the routine you add a *. You have to also select one item as a |distinguished item which is returned by the function among those that |are returned. I don't think this would usually be a problem. Of the set of functions that _must_ return more than one value, a healthy percentage are also modifying a parameter, so the variable will be passed anyway. Of the remaining set, the returned data is usually logically related, so arguably an aggregate of some type should be used. In my opinion, this leaves only a small set of functions which _must_ return more than one value. I do not deem this to be of enough value to change a language (since D is supposedly a successor). |But it is a kludge, and it is prone to error. Throughout the |code you "mean" flag, but sometimes you write &flag, and sometimes you |write *flag, depending on where you are. When actually writing the code, I think the proper form would be clear from the context. Of course, somebody will post a winner of the obfuscated C contest to disprove this statement :-). Quite seriously, I don't believe this to be a problem in _well structured code_. If your functions are well defined, and they are presented clearly in your code, neither the coder nor the maintenance programmer will have much trouble understanding the differences. Such code will also use the power of separate compilation, so there is a good chance these routines will be in separate modules, further eliminating confusion. |A more subtle point is that there is a difference in semantics between |returning a list and passing things through the calling sequence. A |returned value is private unless it is explictly declared as a global; |an item passed through a calling sequence may be a global and the called |routine does not know this. For example, |FILE 1: | int x; | foo () { x = 2; baz(x,&x); } |FILE 2: | extern x; | baz(in,out) int in, *out; | { *out = 1; *out = *out + x; } |is quite different from the same code where baz is a function returning |a value which is declared internally. Your point is well taken. I think the example is somewhat contrived, though. Good program design would eliminate the need(?) for this type of construction. |Call by reference is subject to |unintended aliasing, whether it be real call by reference or simulated |call by reference. Aliasing is not limited to function calls (notice I didn't say unintended aliasing). List return types could save a programmer from some unintentional aliasing problems, and this is a Good Thing. But it doesn't really solve the problem in the first place. Neither does noalias :-). A further note on list returns: Since there is no explicit return variable matching between caller and callee, what would stop the programmer from committing a more serious error, namely reversing or (for more than two returns), switching the returned values around. I rather think this would open a whole new can of worms (how many times have you put the parameters in improperly on a function call?). Think of the additional time spent looking up references to functions, not only to get the parameters right, but also the multiple return values (now, which order did they come in?). A win for passing pointers vs. aggregates: (this does relate - list returns will usually not pass pointers around, but rather entire objects). Then there is the issue of speed and efficiency. I resist the temptation to put structures on the stack when passing parameters. The overhead involved in placing the thing on the stack, operating on it there, then removing it upon return (after copying the values back off the stack) can be large. A pointer to the aggregate works very well, and it is much more likely the machine will have hardware support for handling a pointer. This is both a time and a space win. Moreover, this treatment (passing a pointer) of structs is in keeping with C's treatment of another aggregate, arrays. Treating like classed objects similarly is a win in the clarity and confusion department. |Finally, there is one other annoying consequence of the pointer hack. |You can run into pointer to 0 dereferencing problems if you aren't |careful. You shouldn't, but you can. But this is present wherever pointers are, so in this context it does not really add to your argument. -- --------------------"Well, it looked good when I wrote it"--------------------- Verbal: Dave Burton Net: ...!ihnp4!laidbak!daveb V-MAIL: (312) 505-9100 x325 USSnail: 1901 N. Naper Blvd. #include <disclaimer.h> Naperville, IL 60540
stuart@bms-at.UUCP (Stuart D. Gathman) (03/11/88)
In article <700@l.cc.purdue.edu>, cik@l.cc.purdue.edu (Herman Rubin) writes: > but even for direct operators. For example, the infamous frexp function > in C should not have the syntax > y = frexp(x,&n); > but > y,n = frexp(x); > This would, for example, allow n to be in a register, which is probably > where it should be anyhow. > Another example would be to have > q,r = a///b; > where the quotient and remainder are simultaneously produced. Possibly Another example is string comparison. I use a string compare function that returns the index of the first different character. I also need the gt/lt/eq result. Fortunately, in this case it is easily computed by recomparing the chars at the index. This is another case of a double valued hardware primitive. (Available on all three of the architectures we use: Series/1, 80286, 68020.) -- Stuart D. Gathman <stuart@bms-at.uucp> <..!{vrdxhq|daitc}!bms-at!stuart>
daniels@teklds.TEK.COM (Scott Daniels) (03/12/88)
In article <587@bms-at.UUCP> stuart@bms-at.UUCP (Stuart D. Gathman) writes: >Another example is string comparison. I use a string compare function >that returns the index of the first different character. I also >need the gt/lt/eq result. Fortunately, in this case it is easily >computed by recomparing the chars at the index. An alternative is the string comparison I normally use: cmpstr(s1,s2) 0: if equal >0: if s1 > s2 <0: if s1 < s2 abs(cmpstr(s1,s2)) is the number of chars compared: s1[ abs(cmpstr(s1,s2))-1 ] != s2[ abs(cmpstr(s1,s2))-1 ] if cmpstr did not return 0. Normally this function returns just about any information I need, and it is usually not very hard to make an extremely fast version in assembly. -Scott Daniels (daniels@teklds.TEK.COM)
blu@hall.cray.com (Brian Utterback) (03/17/88)
In article <1354@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes: >In article <25284@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: >>Here is another feature for D whose absence in C has been irksome to >>me -- I would like to be able to return several items from a function. >>... But how do I get stuff back. >>... Things which are returned need a mechanism equivalent to pass >>by address. > >Please don't design D until you understand C. >C has had pass by reference for a very long time (since its inception?). >The following useless code illustrates: > > int flag, foobar(); > x = foobar(&flag); > ... > int foobar(arg) > int *arg; > { > *arg = 1; > return 0; > } >Now, what could be simpler? > Verbal: Dave Burton Net: ...!ihnp4!laidbak!daveb Well, of course that works, but I think the original poster had something else in mind. I think the question was not so much how could you change things passed to the function, but rather how do we pass more than one thing back without changing the original parameters. He still wanted pass by value, but with some mechanism for returning several values. He even mentioned having "in", "out" , and "update" parameters, but rejected these as being unused in current implementations, presumably because users don't like them. For instance, you might want to code a function that emulates a Turing Machine. This function would take a state and an input symbol, and it would return a new state and an output symbol. You could pass 4 parameters, 2 by value for input and 2 by address for the return values, but it would be more natural to want the function to return the 2 values. Personally, I prefer having the extra parameters in the call. I can see where it would be nice to have some form of documenting the parametrs like in,out, and update, but that's more ada than C. Boy, you guys should complain. I used to program APL. We only had 2 input parameters, and one output. And I still liked it alot. Nowadays, you can get APL2 which has multiple input parameters. Feh. The syntax is impenetrable, even for APL. -- Brian Utterback |UUCP:{ihnp4!cray,sun!tundra}!hall!blu | Think of it as Cray Research Inc. |ARPA:blu%hall.cray.com@uc.msc.umn.edu | evolution in One Tara Blvd. #301 | | action Nashua NH. 03062 |Tele:(603) 888-3083 |
kishore@ms.uky.edu (Kishore K. Seshadri) (03/19/88)
> In article <7362@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: > >In article <1020@maccs.UUCP> gordan@maccs.UUCP (gordan) writes: > >technical problems, it must continue to be tolerated. Fix it in "D". All you guys keep talking about "D". Since C came out of BCPL as did the earlier B, the successor to C should really be named "P"... I guess you could say I'm being picky...but this is just for the record. So lets start working on L huh?