If you could change the C or C++ or Java syntax, what would you like different?

L

Lew

Tom said:
As an entirely unrelated aside, why is it that some Americans insist on
referring to all kinds of pasta as spaghetti?

For the same reason they call DVDs "tapes" and they "dial" pushbutton phones?

Metonymy, historicity,
not-giving-a-hoot-about-the-difference-between-rotini-and-farfalle-y?
 
J

Joshua Cranmer

A construct that allows explicit transfer of control to another
statement in order to create control structures more complex than
if-then-else or while-do. Call it "past", e.g.

Don't worry, with BGGA closures, you could probably implement this.

In all seriousness, being able to continue execution from certain
exceptions (like smalltalk's exceptions can do) would be helpful at
times. I can't think of any instances where I wanted to do this off the
top of my head, though.
 
M

Mike Schilling

Joshua Cranmer said:
Don't worry, with BGGA closures, you could probably implement this.

In all seriousness, being able to continue execution from certain
exceptions (like smalltalk's exceptions can do) would be helpful at times.
I can't think of any instances where I wanted to do this off the top of my
head, though.

In _The Design and Evolution of C++_, Stroustrup makes almost exactly this
point. Some exception-handling systems, like VMS's, provided this ability,
but few people used it, and those who did often later removed it as
error-prone. which is why he didn't include it in C++.
 
I

ImpalerCore

(4) Declarations like  char*   a, b, c;
are confusing: a is a pointer but b and c are not.
(It's little problem for most of us, who write instead
    char   *a, b, c;
)

Problem (4) seems like a problem that might afflict any
linear language which, unlike Lisp, is not fully
parenthesized.

For me personally, I still don't like the syntax of having to
associate a pointer type modifier next to the variable declaration.
For me, the difference between char and char* is a difference in type,
and should be reflected in the type portion of the declaration, not a
property of the variable name. I would prefer that 'char* a, b, c;'
declare three char* pointers and just not allow mixed pointer and
regular type declarations on a single line.

Even now, I still declare char pointers using 'char* p' (which I used
coming from a C++ background), and use single line declaration for
each pointer variable. It's probably the most contentious difference
in style that I have with other C coders.
 
T

Tom Anderson

In _The Design and Evolution of C++_, Stroustrup makes almost exactly this
point. Some exception-handling systems, like VMS's, provided this ability,
but few people used it, and those who did often later removed it as
error-prone. which is why he didn't include it in C++.

Stroustrup *didn't* include something in C++ because it was error-prone?
Was he having an off day or something?

Tom
 
S

Seebs

As an entirely unrelated aside, why is it that some Americans insist on
referring to all kinds of pasta as spaghetti?

I have no idea. The generic term I use for pasta is "metalini"*, I consider
something spaghetti only if it's long, round, and a bit thicker than Angel
Hair.

-s
[*] Pasta-shaped pasta, of course.
 
J

Jim Janney

Joshua Cranmer said:
Please share your oppinion on anything you do not like in the C or C++
or Java syntax (they're quite similar).

Let me try int &c in C, List<List<Foo>> in C++, or int *x; in Java. Oh wait.

There is a not-insignificant amount of difference between C, C++, and
Java. The primary things that are really the same between the
languages is the use of curly braces for scope definition,
semicolon-terminated statements, the use of `\' as an escape
character, and the function calling syntax of func(args). The latter
two are common even in those languages which are not curly-braced
delimited (e.g., python), and aren't really anything that people would
complain about.

That pretty much leaves the curly-brace-delimited and
semicolon-delimited natures as the only truly common parts of syntax
which are arguable, and probably anyone who would be inhabiting these
newsgroups are not going to be arguing against those.

I would like to note that many of my... issues with C++ and Java
syntaxes are of those constructs which are (more or less) unique to
those languages [1], so "they're quite similar" isn't good enough.
In order to maintain the integrity of the discussion (have everything
at the same place) please respond on comp.lang.c.

That sounds nice until you realize that many people on the other
newsgroups don't follow comp.lang.c, such as yours truly.

[1] Java generics and C++ templates are sufficiently different that I
am going to call them unique constructs.

I would use = for comparison and := for assignment. You could argue
that this is lexical structure rather than syntax, but it's common to
all three languages.
 
J

Jorgen Grahn

["Followup-To:" header set to comp.lang.c++.]

Stroustrup *didn't* include something in C++ because it was error-prone?
Was he having an off day or something?

Read the book. He describes his (and others') way of reasoning and the
massive field experience he collected in order to make a decision.
And your sarcasm falls flat compared to it.

/Jorgen
 
J

John Bode

For me personally, I still don't like the syntax of having to
associate a pointer type modifier next to the variable declaration.
For me, the difference between char and char* is a difference in type,
and should be reflected in the type portion of the declaration, not a
property of the variable name.  I would prefer that 'char* a, b, c;'
declare three char* pointers and just not allow mixed pointer and
regular type declarations on a single line.

Do you feel the same way about array or function declarators? After
all, you're doing the same thing; applying the type modifier to the
variable name, not the type specifier. It may feel more natural
because the "[]" and "()" operators are postfix and there's no
confusion about whether they should be associated with the declarator
or the type specifier, but it's the exact same issue.

Then you have complex declarations like

int *(*(*f)())[10];

which could not be written as compactly if the dereference operator
was bound to the type specifier as opposed to the declarator (whether
that's a good or bad thing in itself is an open question).

If the dereference operator were made postfix, this whole issue would
go away. And if it were postfix, it would have the same precedence as
"[]", "()", ".", and "->", so you could use operator position to
distinguish between "array of pointer" and "pointer to array", rather
than having to use parentheses to do the grouping:

int x*; // x is a pointer to int
int arr*[10]; // arr is a pointer to a 10-element array of int
int arr[10]*; // arr is a 10-element array of pointer to int
int f*(); // f is a pointer to a function returning int
int f()*; // f is a function returning a pointer to int

Our complex declaration above could be rewritten as

int f*()*[10]*;

which reads pretty easily as "f is a pointer to a function returning a
pointer to a 10-element array of pointer to int".

Of course, this change would probably create as many (if not more)
problems than it solves.

Something that has to be remembered (and isn't emphasized enough in
introductory materials IMO) is that C (*and* C++) declaration syntax
is expression-centric, not object-centric. The reason we declare
pointers as "T *p" is because the type of the *expression* "*p" is
T.

Topic: the only truly unfortunate aspect of C's design is the use of
"=" for assignment and "==" for equality, and that's a lexical issue
rather than syntax. If only the assignment operator had been ":=" or
something similarly unlike the equality operator, then a whole class
of bugs would never have existed.
 
C

ClassCastException

I think the question was about *syntax*, not features. In other words,
which of the *existing* features of the language would you prefer being
able to write using a different syntax.

Closures and semi-anonymous lambdas are an existing feature of Java, if
you abuse some syntactic salt, such as anonymous inner classes:

public interface IntInt {
int foo (int x);
}

/**
* Returns an IntInt that computes the same function as f, but adds amt
* to the output; e.g. if f returns its input return adds amt to its input
* and if f doubles its input return doubles and adds amt.
*/
public class FooExample {
public IntInt addUp (final IntInt f, final int amt) {
return new IntInt () {
public int foo (int x) {
return f.foo(x) + amt;
}
}
}
}

(WARNING: untested code)

Functional programming idioms can be used in Java but presently are
extremely ugly. Compare Scheme-style:

(defun add-up (f amt) (
(lambda (x) (+ amt (f x)))))

Two lines of code, no interface or types, no syntactic salt. Less compile
time type safety though, and you might not care for prefix instead of
infix arithmetic. :)

It's even possible to get a Smalltalkesque return-from-calling-method
capability by abusing RuntimeException, and a Smalltalkesque ability to
do other nonfunctional idioms within closures by passing in and out one-
element arrays or other mutable boxes instead of values.

As for macros, C and C++ have an existing, weak and unsafe macro
facility. Gensyms would go a long way toward addressing the latter. C++
templates provide more of the power of Lisp macros, especially combined
with C++ macros in some cases, but still, clunkier and less safe.

Superior syntax around certain use-cases of templates, and the addition
of a syntax for an anonymous local functor (an implicit local class
declaration and instantiation, implementing the () operator and able to
use variables in the lexically enclosing scope) would go a long way in C+
+.
 
J

John Bode

You did nothing but take up more real estate. call it terminateChar and
its self commented.

Damn you Harter for making me agree with Just Richard, but he's got
some good points here.

[snip]
It does.


More than that.


Then they werent meaningful names. or they were and the programmer was
too lazy to rename them when their usage changed.

[snip]

A truly meaningful name may no longer be *valid* for a particular
context, but its original usage should still be clear from the name.
It shouldn't suddenly become totally meaningless.
No one said that. What was said that excessive commenting is not good as
excessive comments are frequently unnecessary and left to rot.

Agreed. Inline comments should be kept to a minimum.

Which implies a problem in the *process*, not the code. Fix the
process, and those kinds of problems...well, they don't go away, but
they do become more manageable.
Dictionary?!?!? Alphabetize? Did you never hear of local definitions?

If you need a dictionary, you're doing it wrong.
Seriously, what the hell are you talking about?




It should. For a good reason.


And proven in millions of lines of code.


Huh? What are you talking about? You use the local one. if scoping is
now up there with i++ for debate as being confusing then you're in the
wrong job.

It *is* a contrived argument; one of the benefits of keeping
declaration close to usage is that it reduces precisely those kinds of
"oops" moments.
Nonsense. consistency across large code bases is important. That IS a
style.

My experience runs somewhat counter to yours.
 
S

Sir Placenta teh Brave

Please share your oppinion on anything you do not like in the C or C++
or Java syntax (they're quite similar).

In order to maintain the integrity of the discussion (have everything
at the same place) please respond on comp.lang.c.

Cheers,
Alexander

Java, like C/C++? Lol! Java is shite. Once, I read a book on Java, and
within 5 minutes, I had gotten bored. I'm thinking of sticking it in a
bonfire.

--
I'm not a fan of soap operas...unless you're talking about
alt.suicide.holiday.
Official 2010 winner of the "super mega evil luciferian doo doo head
award" from Lisa Ruby.
Previously known as "zx386," but recently given the title "Sir Placenta
the Brave."
 
B

BartC

John Bode said:
On Oct 11, 9:33 am, ImpalerCore <[email protected]> wrote:
Then you have complex declarations like

int *(*(*f)())[10];

which could not be written as compactly if the dereference operator
was bound to the type specifier as opposed to the declarator (whether
that's a good or bad thing in itself is an open question).

If the dereference operator were made postfix, this whole issue would
go away. And if it were postfix, it would have the same precedence as
"[]", "()", ".", and "->", so you could use operator position to
distinguish between "array of pointer" and "pointer to array", rather
than having to use parentheses to do the grouping:

int x*; // x is a pointer to int
int arr*[10]; // arr is a pointer to a 10-element array of int
int arr[10]*; // arr is a 10-element array of pointer to int
int f*(); // f is a pointer to a function returning int
int f()*; // f is a function returning a pointer to int

Our complex declaration above could be rewritten as

int f*()*[10]*;

which reads pretty easily as "f is a pointer to a function returning a
pointer to a 10-element array of pointer to int".

Not as easily as the English; and the name is still in the middle instead of
at either end. And the "int" specifier, although dominant, is actually a
minor part of the type spec (after the first pointer is dereferenced, the
function called, the result [dereferenced and] indexed, and dereferenced yet
again, *then* you have the int result).

In fact, why *not* allow the declaration to be in English, since no-one is
going to agree on any new compact syntax? Eg.

declare f "pointer to function returning a pointer to a (10) element array
of pointer to int";

where "to", "returning", "a", "element", "array", and "of" are optional.
Topic: the only truly unfortunate aspect of C's design is the use of
"=" for assignment and "==" for equality, and that's a lexical issue
rather than syntax. If only the assignment operator had been ":=" or
something similarly unlike the equality operator, then a whole class
of bugs would never have existed.

Actually I think ":=" can still be introduced to C, and be used as an
alternative to "=".

This won't immediately solve the "="/"==" problem, but if I was writing
":="/"==" all the time, then I think a lone "=" would stand out.
 
B

Ben Bacarisse

My apologies for being unclear. I dare say I was thinking of
rather more than what I actually wrote. My preferred style is to
have one declaration per line with an optional initializer, an
optional comment, and with each element of the declaration
vertically aligned. For example programmer X writes

char *b, endchar;

and I might write the same as

char *b = 0; /* Ptr to beginning of foo */
char endchar; /* Terminating character of scan */

The thought is to create a dictionary for the scope, a dictionary
that contains the terms that are used within the scope. Like all
good dictionaries it contains definitions and is organized so
that terms are easy to find.

Right. I thought that might be what you meant. I used to do that but
I've gone off this style. One reason is simply a silly OCD one. I
don't like it when the explanation causes the comment to be multi-line
so I found myself mentally editing my comments to the point where they
were often ambiguous. Your "Terminating character of scan" has already
shown this effect in this thread.

I've switched to block comments. Often, these don't refer the variables
directly but instead they tell a story (in tiny pieces of course) so,
for example, I might write:

/* Scan the buffer for the first non-digit found to follow the
* exponent. The terminating null ensures there always will be
* such a character.
*/
char *cp = buffer, first_non_digit;

<snip>
 
B

Ben Bacarisse

John Bode said:
If the dereference operator were made postfix, this whole issue would
go away. And if it were postfix, it would have the same precedence as
"[]", "()", ".", and "->", so you could use operator position to
distinguish between "array of pointer" and "pointer to array", rather
than having to use parentheses to do the grouping:

int x*; // x is a pointer to int
int arr*[10]; // arr is a pointer to a 10-element array of int
int arr[10]*; // arr is a 10-element array of pointer to int
int f*(); // f is a pointer to a function returning int
int f()*; // f is a function returning a pointer to int

The issue does not quite go away. There is still the matter of type
qualifiers -- do they still attach to the "base type" or do they, too,
follow the variable. When you include these as post-fix modifiers it
may strike you that you could do the same with the base type as well --
make that post-fix too and the declaration becomes uni-directional.

Of course you can decide if you now want to switch and make everything
pre-fix, but other languages, like Algol 68, use the left to right order
only they put the name at the end rather than in front to the type:
Our complex declaration above could be rewritten as

int f*()*[10]*;

With post-fix base types:

f*()*[10]* int;

In Algol 68 the name goes after the type but the order of the
"declarators" (not an Algol 68 term) is the same as you have here:

ref proc() ref [10] ref int f;

[You would not use all those refs in typical Alog 68 but that's not the
point here.]
 
B

BartC

Ben Bacarisse said:
int x*; // x is a pointer to int
int arr*[10]; // arr is a pointer to a 10-element array of int
int arr[10]*; // arr is a 10-element array of pointer to int
int f*(); // f is a pointer to a function returning int
int f()*; // f is a function returning a pointer to int
Our complex declaration above could be rewritten as

int f*()*[10]*;

With post-fix base types:

f*()*[10]* int;

In Algol 68 the name goes after the type but the order of the
"declarators" (not an Algol 68 term) is the same as you have here:

ref proc() ref [10] ref int f;

I've never used Algol68 but make use of pretty much the same syntax (the
above would be ref proc: ref [10] ref int f, although I prefer 'function' to
'proc').

That looks great, and reads almost like English (better than actual Algol68
which always seems to require capitals or quoting for reserved words).

And an extra advantage is being able to share a complex declaration amongst
several identifiers, without messing with typedefs:

ref function: ref [10] ref int f, g, h

This applies to prototype declarations too, when many functions share the
same signature.
[You would not use all those refs in typical Alog 68 but that's not the
point here.]

[Why not?]
 
I

ImpalerCore

For me personally, I still don't like the syntax of having to
associate a pointer type modifier next to the variable declaration.
For me, the difference between char and char* is a difference in type,
and should be reflected in the type portion of the declaration, not a
property of the variable name.  I would prefer that 'char* a, b, c;'
declare three char* pointers and just not allow mixed pointer and
regular type declarations on a single line.

Do you feel the same way about array or function declarators? After
all, you're doing the same thing; applying the type modifier to the
variable name, not the type specifier.  It may feel more natural
because the "[]" and "()" operators are postfix and there's no
confusion about whether they should be associated with the declarator
or the type specifier, but it's the exact same issue.

I still like the array postfix modifier the way its designed. So in
that sense it's somewhat hypocritical of me to advocate keeping the
pointer modifier to the type portion while still being ok with an
array modifier attached to the variable name. I suppose that it's
simply because the array postfix '[]' is so ubiquitous between many
different languages that it's not easily confused.

Most of my bias is probably due to learning programming from the
Stroustrup's C++ book, where declaring both pointers and references
were modifiers of the type portion of the variable declaration. The
choice of using '&' to declare references means that the potential for
confusion between declaring a reference type and referencing the
address of a variable would be much higher. My guess is that
Stroustrup's intent was to distinguish using the '&' as a prefix
operator to signify taking the address of a variable, from using '&'
as a postfix operator to signify a type modifier used to declare a
'reference to type'.

In the same manner, the style of using '*' in his book is used as a
prefix operator to signify pointer dereference, and as a postfix
operator of a type to modify it to a 'pointer to type'. When I got to
C, now people wanted to use prefix '*' to mean both, which due to my
history I find more confusing, and definitely feel resistance to
adopt.

As far as function pointers, they are in their own category and I'm
not sure whether I like them or not. It certainly took some time to
get used to them, but I can't think of an alternate syntax since
functions declaration themselves have return type prefixes and
argument postfix modifiers. I certain would be resistant to any
change in function pointer or declaration semantics now.
Then you have complex declarations like

    int *(*(*f)())[10];

which could not be written as compactly if the dereference operator
was bound to the type specifier as opposed to the declarator (whether
that's a good or bad thing in itself is an open question).

If the dereference operator were made postfix, this whole issue would
go away.  And if it were postfix, it would have the same precedence as
"[]", "()", ".", and "->", so you could use operator position to
distinguish between "array of pointer" and "pointer to array", rather
than having to use parentheses to do the grouping:

    int x*;        // x is a pointer to int
    int arr*[10];  // arr is a pointer to a 10-element array of int
    int arr[10]*;  // arr is a 10-element array of pointer to int
    int f*();      // f is a pointer to a function returning int
    int f()*;      // f is a function returning a pointer to int

Our complex declaration above could be rewritten as

    int f*()*[10]*;

which reads pretty easily as "f is a pointer to a function returning a
pointer to a 10-element array of pointer to int".

Of course, this change would probably create as many (if not more)
problems than it solves.

Something that has to be remembered (and isn't emphasized enough in
introductory materials IMO) is that C (*and* C++) declaration syntax
is expression-centric, not object-centric.  The reason we declare
pointers as "T *p" is because the type of the *expression* "*p" is
T.

Strange, but it is Stroustrup's coding style in his own book that
advocated postfix modifiers for declaring pointer and reference
variables, so the C++ part of your statement is likely not true. I
don't recall if K&R mentioned if there was any motive behind their
choice for pointer variable declaration syntax. Now pointer syntax
has the weight of history behind it, and I know that my pointer
declaration preferences will likely remain an outlier opinion in C
because of it.
Topic: the only truly unfortunate aspect of C's design is the use of
"=" for assignment and "==" for equality, and that's a lexical issue
rather than syntax.  If only the assignment operator had been ":=" or
something similarly unlike the equality operator, then a whole class
of bugs would never have existed.

Seems reasonable. It certainly would have mitigated the whole '0 ==
variable' use, which I can't stand from a style perspective.
Backwards code my read to like I.

Best regards,
John D.
 
J

John Bode

[snip]
Something that has to be remembered (and isn't emphasized enough in
introductory materials IMO) is that C (*and* C++) declaration syntax
is expression-centric, not object-centric.  The reason we declare
pointers as "T *p" is because the type of the *expression* "*p" is
T.

Strange, but it is Stroustrup's coding style in his own book that
advocated postfix modifiers for declaring pointer and reference
variables, so the C++ part of your statement is likely not true.  

As far as the language grammar is concered, it is. Here's a grammar
trace for a simple pointer declaration "int* p;" (taken from
http://www.open-std.org/jtc1/sc22/open/n2356/gram.html):

declaration
|
block-declaration
|
simple-declaration
/ \
decl-specifier-seq init-declarator-list
| |
type-specifier init-declarator
| |
simple-type-specifier declarator
| / \
int ptr-operator declarator
| |
* direct-declarator
|
id-expression
|
unqualified-id
|
identifier
|
p

The '*' operator is bound to the declarator (the trace for a reference
declaration is identical, as '&' is also a production of ptr-
operator). I get what Stroustrup is saying, and I've done enough C++
to see where that approach makes certain things easier (particularly
in a generic container type), but unfortunately the language grammar
doesn't work that way.
 
T

Tom Anderson

Seebs said:
[...] I consider something spaghetti only if it's long, round, and a
bit thicker than Angel Hair.

[*] Pasta-shaped pasta, of course.

It sounds like you are suggesting the C Standard Committee to add the
"spaghetti integer" data type. Beware the oven-flows! :)

It's ideal for use in layered architectures. Along with plenty of ragu and
bechamel sauce.

tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top