mayer@iuvax.cs.indiana.edu (Mayer Goldberg) (12/11/90)
Pascal programmers who learn C, frequently complain of C's
lack of a "with" construct. We propose an alternative to
adding such a keyword, through a natural extention of C's
aggregate initialization statement.
Consider the following program fragment:
struct ag {
int a, b, c;
};
struct ag my_vec = {1, 2, 3};
This form of an "assignment" is permitted only during the
initialization of a variable (at compile time). Any other way
of assignment to fields in my_vec will have to be done by routing
through my_vec, as in:
my_vec.a = 4; my_vec.c = 7; /* etc. */
We submit that a better way of doing this would be to allow a
kind of assignment that we allow during initialization.
Something like:
my_vec = {4,, 7};
If for example we wished to assign 2 and 3 to the 'a' and 'b'
fields of my_vec, any one of the following should be ok:
my_vec = {2, 3};
or
my_vec = {2, 3,};
This mechanism should work for both structures and arrays.
This solves the "with" problem in C. It also opens a delicious
can of worms: Should the order of evaluation of the aggregated
expressions be specified? Perhaps not, for this would be in
line with C's philosophy of not specifying the order of
evaluation of parameters to a function, or alternately, we
could demand a left-to-right order of evaluation as implied by
the comma operator.
Mayer Goldberg Nick Cline
mayer@iuvax.cs.indiana.edu cline@silver.ucs.indiana.edu
gwyn@smoke.brl.mil (Doug Gwyn) (12/11/90)
In article <77546@iuvax.cs.indiana.edu> mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: >This solves the "with" problem in C. Doing nothing is even better. "with" is insufficiently general, in that it cannot discriminate between similarly named members of different structsures that you might want to be working "with" simultaneously. "Not looking like Pascal is not a language deficiency."
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (12/11/90)
In article <77546@iuvax.cs.indiana.edu>, mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: > We submit that a better way of doing this would be to allow a > kind of assignment that we allow during initialization. > Something like: > my_vec = {4,, 7}; If you want Ada, you know where to find it. It you want to make it easy for people to introduce subtle and difficult-to-locate mistakes in their programs, keep it up. A better approach is to write a function that fills in records struct ag mk_ag(int a, int b, int c) { struct ag ans; ans.a = a, ans.b = b, ans.c = c; return ans; } Then the struct declaration can have new fields added, or the fields re-ordered, and my_vec = mk_ag(4, 0, 7); will still work. (Hint: this is why Ada record constructors let you use keywords.) If your compiler supports inlining (gcc, for example) struct-building functions are good candidates for inlining. -- The Marxists have merely _interpreted_ Marxism in various ways; the point, however, is to _change_ it. -- R. Hochhuth.
steve@taumet.com (Stephen Clamage) (12/11/90)
mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: |Pascal programmers who learn C, frequently complain of C's |lack of a "with" construct. We propose an alternative to |adding such a keyword, through a natural extention of C's |aggregate initialization statement. |[example] |struct ag { | int a, b, c; |}; |struct ag my_vec = {1, 2, 3}; You could just use C++, which already allows such things via constructors. -- Steve Clamage, TauMetric Corp, steve@taumet.com
dgil@pa.reuter.COM (Dave Gillett) (12/12/90)
In <77546@iuvax.cs.indiana.edu> mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: >Pascal programmers who learn C, frequently complain of C's >lack of a "with" construct. We propose an alternative to >adding such a keyword, through a natural extention of C's >aggregate initialization statement. . . . >This solves the "with" problem in C. It also opens a delicious >can of worms: Should the order of evaluation of the aggregated >expressions be specified? Perhaps not, for this would be in >line with C's philosophy of not specifying the order of >evaluation of parameters to a function, or alternately, we >could demand a left-to-right order of evaluation as implied by >the comma operator. On the contrary, it solves a *piece* of the "with" problem, and introduces a can of worms which is not only delicious, but not present in the Pascal "with" construct. Mayer's suggestion covers the case of aggregate assignment *to* a struct, but does not even attempt to address references to struct elements as anything other than targets of assignment. Since Pascal's "with" applies to all element references, regardless of context, the suggested enhancement cannot be mistaken for an equivalent feature. If the comma is to be used, it seems preferable for it to retain as much of its normal semantics as possible. Indeed, I think it is already a linguistic flaw for it to have different semantics as an argument delimiter than as an operator. Introducing a third semantics for a single symbol is clearly not a good idea. Using the operator semantics should, it seems, yield a single rvalue for the expression within the {}s. [No, I didn't quote Mayer's entire article.] So that leaves the function parameter semantics. (At the moment, {} have different semantics depending on whether one is looking at a variable declaration or at code; leaking the variable definition semantics of {} over into code, where they already have their own semantics, seems dubious.) Suppose, having decided to use the argument delimiter semantics of the comma, we also steal the accompanying () semantics. So "(a, b, ...)" is a "list of values" construct, which can be assigned to a structure (under suitable constraints) or passed as an argument list to a function. (So "()" is the empty list.) So far, this looks like a powerful generalization that shouldn't break existing code. The problem is that, if we define the paren/comma construct this way, then "funcname structname;" should call function "funcname" passing the values from struct "structname" as arguments. That might be nice, but it's not C. Note that "funcname structname" is *not* equivalent to "funcname (structname)". The latter function takes a single struct as an argument, not the elements of the struct as list of arguments. You can make them equivalent in the compiler, but that gives you no way to have a struct as one of a list of arguments, and so breaks existing code. Mayer's suggestion points in the direction of APL's nested arrays or LISP's lists. But it's not C, and it's not Pascal's "with", either. Dave
bson@rice-chex.ai.mit.edu (Jan Brittenson) (12/13/90)
In article <77546@iuvax.cs.indiana.edu> mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: >Consider the following program fragment: > >struct ag { > int a, b, c; >}; > >struct ag my_vec = {1, 2, 3}; > >This form of an "assignment" is permitted only during the >initialization of a variable (at compile time). Perhaps you should take a look at GNU C. Its aggregate initializer doesn't allow you to "skip" members, but I fid it much more useful than Pascal's WITH clause. /* Feed me to GCC! */ #include <stdio.h> struct barf { int x, y; }; void print_barf(barfstuff) struct barf barfstuff; { printf("barf: x=%d, y=%d\n", barfstuff.x, barfstuff.y); } main() { print_barf( (struct barf) {2, 3} ); }
heidi@ctk1.UUCP (Heidi de Wet) (12/14/90)
In <4479@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: >In article <77546@iuvax.cs.indiana.edu>, mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: >> [Proposed alternative to 'with' construct] >> We submit that a better way of doing this would be to allow a >> kind of assignment that we allow during initialization. >> Something like: >> my_vec = {4,, 7}; As a staunch fan of Pascal, writing C for a living :-), this seems a very uninteresting problem. Pascal's 'with' doesn't solve this, anyway. It _does_ reduce the text associated with multiple references to the same record structure in one expression. Try this for size: (*Buff)->Msg_Bytes [(*Buff)->Start_Index + (*Buff)->Byte_Count] = B; Now try copying one 'Buff' to another... Any suggestions about this? If you want to make assignments of multiple elements in a structure easier, how about the construct 'A = B', where A and B are identical, complex structs or arrays? Yes, you can use memcpy, but it would be nice to see the compiler doing a _little_ bit of work for a change. >If you want Ada, you know where to find it. >It you want to make it easy for people to introduce subtle and >difficult-to-locate mistakes in their programs, keep it up. Well, that would be entirely in the spirit of C, wouldn't it? -------------------- Heidi de Wet University of Cape Town, South Africa ddsw1!proxima!ctk1!heidi -or- proxima!ctk1!heidi@ddsw1.mcs.com
jmd@dlogics.COM (Jens M. Dill) (12/18/90)
In article <1990Dec14.130916.18447@ctk1.UUCP>, heidi@ctk1.UUCP (Heidi de Wet) writes: > >In article <77546@iuvax.cs.indiana.edu>, mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: > >> [Proposed alternative to 'with' construct] > >> We submit that a better way of doing this would be to allow ... > >> Something like: my_vec = {4,, 7}; > > As a staunch fan of Pascal, writing C for a living :-), this seems a > very uninteresting problem. Pascal's 'with' doesn't solve this, anyway. > It _does_ reduce the text associated with multiple references to the > same record structure in one expression. Try this for size: > > (*Buff)->Msg_Bytes [(*Buff)->Start_Index + (*Buff)->Byte_Count] = B; If you are willing to step outside of comp.lang.C for a moment, note that C++ reference types handle this very nicely: { BuffStructType & BF = **Buff ; /* Yes, you did have a double ... indirection in your code */ BF.Msg_Bytes [BF.Start_Index + BF.Byte_Count] = B ; } In short: the Pascal WITH statement allows you to completely elide a complex qualifying expression on the front of a structure reference, at the cost of only being able to do so for one structure of a given type at any one time. C++ references allow you to replace a complex qualifying expression with what looks like a simple reference to a field of a named structure. You can't get rid of that last qualifier, but you can make it short and you do get the freedom to do it to more than one structure of the same type. By the way, C purists can do almost the same thing with pointers: { BuffStructure * BP = *Buff ; BP->Msg_Bytes [BP->Start_Index + BP->Byte_Count] ; } Don't let the cost of the "extra" variable fool you. It's saving you time by precomputing most of the common addressing information. A smart compiler will manage to keep the new variable in a register for its entire scope, if, like this, it's VERY local and frequently used. If you don't have a smart compiler, you can declare it a register variable. > Now try copying one 'Buff' to another... Any suggestions about this? > > If you want to make assignments of multiple elements in a structure > easier, how about the construct 'A = B', where A and B are identical, > complex structs or arrays? ... "A = B" works fine for structures, provided A and B are the same type of structure. It didn't work in the earliest versions of C, (and is not in K&R 1), but unless you have a very old C compiler it should work for you. Arrays are a whole different kettle of fish, as any regular reader of this newsgroup will tell you. You can get what you want by embedding the array inside a structure and assigning the structure, however. But the original poster didn't have two identical structures, but rather wanted to be able to initialize a structure dynamically with a constant value for each of the fields. C allows you to do this statically (at compile time, into a global or static variable), but does not have an equivalent run-time initialization for automatic structures. Neither does Pascal. C++ allows you to fake it by writing a "constructor function" to do the initialization on the fly, but that brings in a whole bunch of new syntax and semantics that are not at all related to the static initialization ("= { ... }") idea. The best solution is to define a static "constant" structure that can be initialized using the "= { ... }" notation, and then initialize your automatic variable by a simple assignment from the static "constant": void foo (args ...) { static struct MyStruct Initializer = { ... } ; struct MyStruct LocalStructVar = Initializer ; ... } You may have to split the second declaration into a declaration and an assignment statement if your compiler is overly rigid about not allowing any initialization of automatic variables. *=====* TIME CANNOT BE WASTED *=====* -- Jens M. Dill \ But it can be used for purposes / jmd@dlogics.com \ other than what was intended. / *=============================*
smryan@garth.UUCP (Steven Ryan) (12/20/90)
>my_vec.a = 4; my_vec.c = 7; /* etc. */ > >We submit that a better way of doing this would be to allow a . . . > >my_vec = {4,, 7}; As I live and breathe--structure displays again, and after only 22 years. Two points to consider: (1) Can you handle single element structures? When Ada tried, they really screwed it up, even though a quick perusal of Algol 68 would have pointed this out early in the game. (2) The mode of of structure display cannot be synthesised: given the types of the elements, you cannot generally determine the structure. In Algol a structure display can only occur in strong position. (A not-so-quick perusal of Algol will point out the dangers here.) And for Ritchie's sake [*], don't screw up this ripof--err--borrowing the same way +:= was screwed up to =+. __________________________________________________ * I apologise to those who are offended by taking the Lord's name in vain, bit I do get a teensy bit irritated some times. -- ...!uunet!ingr!apd!smryan Steven Ryan ...!{apple|pyramid}!garth!smryan 2400 Geng Road, Palo Alto, CA
mat@mole-end.UUCP (Mark A Terribile) (12/23/90)
In article <538@taumet.com>, steve@taumet.com (Stephen Clamage) writes: > mayer@iuvax.cs.indiana.edu (Mayer Goldberg) writes: > |Pascal programmers who learn C, frequently complain of C's > |lack of a "with" construct. We propose an alternative to > |adding such a keyword, ... > |[example] > |struct ag { > | int a, b, c; > |}; > |struct ag my_vec = {1, 2, 3}; > You could just use C++, which already allows such things via constructors. Note also that C++ has much less use for the `with' because sequences of `` abc. ... '' and `` def-> ... '' tend to be absorbed into member functions where they are not written when the function is called on behalf of the structure object. On the other hand, if someone is uncomfortable with C because he's just come from another environment (such as one which will remain nameless except that it's named after a fellow name Blaise Pascal, who did nothing at all to deserve it) sending him to C++ is the LAST thing you want to do. First, because C++ has even a stronger flavor than C. Second, because someone who realizes that it's possible to do almost ANYTHING in C++, without learning the C mindset as a stepping stone is liable to try some strange things. They might not work, but we can't count on it. -- (This man's opinions are his own.) From mole-end Mark Terribile