Extending C syntax

J

john

Hi

We know that C has been through several revisions since it was first
created by Kernigan and Richie. One thing I don't understand is why some
of the opportunities for expansion present in the original C
specification have not been taken up in these subsequent revisions.

Here are two examples.

1. C does not have a ||= operator (or for that matter a &&= operator).
This is extremely useful and elegant in Perl for specifying default
values and it could work just the same way in C.

2. There are lots of operations that we often need to perform on pointers
to the same block of memory, e.g. find the max or min, or the average of
them, and many others. There are also lots of arithmetic operations that
are not currently defined for pointers, in fact only minus (ptrdiff_t) is
defined. So why not extend the syntax so that unused operators like +,
*, /, %, ^, &, etc would implement these useful operations.

For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

instead of a complicated expression with lots of terms.
 
S

Seebs

1. C does not have a ||= operator (or for that matter a &&= operator).
This is extremely useful and elegant in Perl for specifying default
values and it could work just the same way in C.

No it couldn't, because "a || b" in C yields true if either is not zero,
but in perl, it yields a if a is not zero, otherwise b.

You'd have to change || to provide ||= cleanly.
2. There are lots of operations that we often need to perform on pointers
to the same block of memory, e.g. find the max or min, or the average of
them, and many others. There are also lots of arithmetic operations that
are not currently defined for pointers, in fact only minus (ptrdiff_t) is
defined. So why not extend the syntax so that unused operators like +,
*, /, %, ^, &, etc would implement these useful operations.

I'm not sure I understand.
For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;

I think this is too surprising to be a good extension. I would never
guess what you came up with for its possible meaning.

-s
 
B

bart.c

2. There are lots of operations that we often need to perform on pointers
to the same block of memory, e.g. find the max or min, or the average of
them, and many others. There are also lots of arithmetic operations that
are not currently defined for pointers, in fact only minus (ptrdiff_t) is
defined. So why not extend the syntax so that unused operators like +,
*, /, %, ^, &, etc would implement these useful operations.

For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

instead of a complicated expression with lots of terms.

You would just end up with APL..

It's better to define a few functions then just write:

johns_search(int *first, int n)
{
int *mid = int_average(first,n);
 
E

Eric Sosman

Hi

We know that C has been through several revisions since it was first
created by Kernigan and Richie.

(Sigh.) At the very least, as a bare minimum, use correct
spellings for the names of your betters. Got it, Jean?
One thing I don't understand is why some
of the opportunities for expansion present in the original C
specification have not been taken up in these subsequent revisions.

Possibly because they're underspecified?
Here are two examples.

1. C does not have a ||= operator (or for that matter a&&= operator).
This is extremely useful and elegant in Perl for specifying default
values and it could work just the same way in C.

Sorry; not a Perlfisher. But in C, the result of || and
of && is 0 or 1. So, one presumes that `x &&= y' would produce
0 if x is 0, 0 if y is zero, 1 otherwise. And `x ||= y' would
yield 1 if x is non-zero, 1 if y is non-zero, 0 otherwise. I
fail to see a tremendous utility in either construct.
2. There are lots of operations that we often need to perform on pointers
to the same block of memory, e.g. find the max or min, or the average of
them, and many others. There are also lots of arithmetic operations that
are not currently defined for pointers, in fact only minus (ptrdiff_t) is
defined.

Nonsense. You'll also find <, <=, ==, >=, >, !=, defined for
pairs of pointer operands satisfying suitable conditions. Also
+ and - and [] for legitimate combinations of pointers and integers.
So why not extend the syntax so that unused operators like +,
*, /, %, ^,&, etc would implement these useful operations.

For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

Sorry; what is this supposed to signify? I see a syntactically
valid but meaningless (and constraint-violating, as things stand)
construct, but what do you imagine it would mean?
instead of a complicated expression with lots of terms.

Maybe you should exhibit the "complicated expression with lots
of terms" you think this thing ought to mean. (Aww, no; where's
the fun in *defining* things when you can do hand-waving instead?)
 
P

Peter Nilsson

john said:
We know that C has been through several revisions since it
was first created by Kernigan and Richie [sic]. One thing
I don't understand is why some of the opportunities for
expansion present in the original C specification have not
been taken up in these subsequent revisions.

Because the mandate for WG14 is to standardise existing
practice. In other words, they're not there to invent or
reinvent C. Rather, they are there to codify the core
elements of what every C implementation should have as
a minimum if it wishes to be classified as conforming.
 
E

Eric Sosman

Eric said:
[... arithmetic operators with two pointer operands ...]
For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

Sorry; what is this supposed to signify? I see a syntactically
valid but meaningless (and constraint-violating, as things stand)
construct, but what do you imagine it would mean?
instead of a complicated expression with lots of terms.

Maybe you should exhibit the "complicated expression with lots
of terms" you think this thing ought to mean.

It would be

int *mid = (last - first) / 2 + first;

In "fairy C" you can define anything any way you like, of course,
but I can't see any mnemonic connection between the two expressions.
Perhaps if you suggested `(first + last) / 2' a case could be made,
but `first / last'? Why should that be understood as "the midpoint
between first and last?" It's not, for example, how you calculate
the midpoint between two ordinary numbers: 1/10 is 0 or 0.1 depending
on types, but the midpoint between 1 and 10 is nowhere near either.
To my eye, your suggestion seems arbitrary -- which may just mean I'm
too dense to discern the underlying logic, but sqrt(first * last) looks
equally sensible to me.
 
R

Richard Bos

pete said:
It would be

int *mid = (last - first) / 2 + first;

No, no, it said _complicated_ expression with _lots_ of terms. Not
_obvious_ expression with _a couple_ of terms.

Richard
 
J

john

Eric said:
Eric said:
On 5/12/2010 6:44 PM, john wrote:
[... arithmetic operators with two pointer operands ...] For example,
if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

Sorry; what is this supposed to signify? I see a syntactically
valid but meaningless (and constraint-violating, as things stand)
construct, but what do you imagine it would mean?

instead of a complicated expression with lots of terms.

Maybe you should exhibit the "complicated expression with lots
of terms" you think this thing ought to mean.

It would be

int *mid = (last - first) / 2 + first;

In "fairy C" you can define anything any way you like, of course,
but I can't see any mnemonic connection between the two expressions.
Perhaps if you suggested `(first + last) / 2' a case could be made, but
`first / last'? Why should that be understood as "the midpoint between
first and last?" It's not, for example, how you calculate the midpoint
between two ordinary numbers: 1/10 is 0 or 0.1 depending on types, but
the midpoint between 1 and 10 is nowhere near either. To my eye, your
suggestion seems arbitrary -- which may just mean I'm too dense to
discern the underlying logic, but sqrt(first * last) looks equally
sensible to me.

I think you are being deliberately obtuse here.

The point is that at present, if p and q are pointers, then p / q has no
meaning, so you lose nothing and gain some brevity by giving it a
meaning. I chose as an example defining "p / q" to be the average of p
and q, i.e. q - (q - p) / 2. You could instead define p & q to be the
average and p / q to be the minimum of p and q - whatever you wanted, or
whatever the standards body finds most mnemonic if you like.

As long as it was standardized, everyone would be on the same page.
 
B

bart.c

john said:
Eric Sosman wrote:

I think you are being deliberately obtuse here.

The point is that at present, if p and q are pointers, then p / q has no
meaning, so you lose nothing and gain some brevity by giving it a
meaning. I chose as an example defining "p / q" to be the average of p
and q, i.e. q - (q - p) / 2.

If you're going to have a special operator for the average of just 2 (not
even N) values, you'd expect to apply it to 2 integers or 2 floats. But if
it can only be applied to pointers, it hardly seems worthwhile.
You could instead define p & q to be the
average and p / q to be the minimum of p and q - whatever you wanted, or
whatever the standards body finds most mnemonic if you like.

If we're going to be adding things, using average(a,b) and min(p,q), which
would work for all scalar types, would be a better bet.
 
R

Rui Maciel

john said:
Hi

We know that C has been through several revisions since it was first
created by Kernigan and Richie. One thing I don't understand is why some
of the opportunities for expansion present in the original C
specification have not been taken up in these subsequent revisions.

Here are two examples.

1. C does not have a ||= operator (or for that matter a &&= operator).
This is extremely useful and elegant in Perl for specifying default
values and it could work just the same way in C.

2. There are lots of operations that we often need to perform on pointers
to the same block of memory, e.g. find the max or min, or the average of
them, and many others. There are also lots of arithmetic operations that
are not currently defined for pointers, in fact only minus (ptrdiff_t) is
defined. So why not extend the syntax so that unused operators like +,
*, /, %, ^, &, etc would implement these useful operations.

For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

instead of a complicated expression with lots of terms.

Other than syntactic sugar and needless bloat, what objective benefits do you believe your
proposed extensions bring to the language?


Rui Maciel
 
S

Seebs

I think you are being deliberately obtuse here.

I don't think so.
The point is that at present, if p and q are pointers, then p / q has no
meaning, so you lose nothing and gain some brevity by giving it a
meaning.

Actually, you lose something big -- consistency.

Unless the meaning is reasonably clear to everyone as "what it would mean
to divide pointers", it's *worse* than simply not having a meaning.
As long as it was standardized, everyone would be on the same page.

I don't think it works that way.

I mean, you could define unary-* on integers, so that '*1' meant something.
But unless what it meant was sufficiently similar to the meaning of '*p' on
a pointer, it would be *confusing*, and you'd lose a great deal.

Consider that C++ has standardized a great number of interesting overloaded
operators, and that many of them are still consistently confused and mistaken
for each other because the overloadings aren't obvious.

That said, if you wanted to make an interesting extension allowing operations
on pairs of pointers, I'd say do it by introducing a new type, which is
essentially a bounded region. So you could do something like
int *p, *q, *r;
/* initialize p and q */
int bound x;
x = p + q; /* x is now the range [p,q) */
r = x / 2; /* r is now the midpoint of the range [p,q) */

That *might* work -- if it were intuitive to enough people, and if someone
implemented it, and if people found it useful.

I doubt they would.

It might be interesting to try to implement something like this (your
suggestion or mine, doesn't matter which) in C++ and see whether anyone
uses it. If they don't, there's not much point.

-s
 
J

john

Eric said:
(Sigh.) At the very least, as a bare minimum, use correct
spellings for the names of your betters. Got it, Jean?

Whatever. I don't have the book to hand to double check the spellings.
Possibly because they're underspecified?
??


Sorry; not a Perlfisher. But in C, the result of || and
of && is 0 or 1. So, one presumes that `x &&= y' would produce 0 if x
is 0, 0 if y is zero, 1 otherwise. And `x ||= y' would yield 1 if x is
non-zero, 1 if y is non-zero, 0 otherwise. I fail to see a tremendous
utility in either construct.

I think you are being deliberately obtuse here.

As ||= currently has no meaning, the standards body is free to assign it
any meaning it chooses - it doesn't *need* to be consistent with ||. I
agree that it would be preferable if it was, but if it became a common
idiom then I think people would quickly adjust to it and it wouldn't
cause significant confusion.
 
R

Rui Maciel

john said:
I think you are being deliberately obtuse here.

The point is that at present, if p and q are pointers, then p / q has no
meaning, so you lose nothing and gain some brevity by giving it a
meaning.

I beg to differ. The operator / has an established use: the division operation. If the division
operator suddenly starts to also mean "the average of two addresses pointed to by two given
pointers", specially in a language which doesn't support operator overloading, then the / operator
would lose coherence in it's meaning.

I chose as an example defining "p / q" to be the average of p
and q, i.e. q - (q - p) / 2. You could instead define p & q to be the
average and p / q to be the minimum of p and q - whatever you wanted, or
whatever the standards body finds most mnemonic if you like.

What's wrong with writing a function for that?

As long as it was standardized, everyone would be on the same page.

How many people have to calculate the average of the addresses pointed to by two pointers? Could
you please provide an example where you regularly employ this operation?


Rui Maciel
 
K

Keith Thompson

john said:
Eric Sosman wrote: [...]
On 5/12/2010 6:44 PM, john wrote:
[... arithmetic operators with two pointer operands ...] For example,
if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...
[snip]
In "fairy C" you can define anything any way you like, of course,
but I can't see any mnemonic connection between the two expressions.
Perhaps if you suggested `(first + last) / 2' a case could be made, but
`first / last'? Why should that be understood as "the midpoint between
first and last?" It's not, for example, how you calculate the midpoint
between two ordinary numbers: 1/10 is 0 or 0.1 depending on types, but
the midpoint between 1 and 10 is nowhere near either. To my eye, your
suggestion seems arbitrary -- which may just mean I'm too dense to
discern the underlying logic, but sqrt(first * last) looks equally
sensible to me.

I think you are being deliberately obtuse here.

The point is that at present, if p and q are pointers, then p / q has no
meaning, so you lose nothing and gain some brevity by giving it a
meaning. I chose as an example defining "p / q" to be the average of p
and q, i.e. q - (q - p) / 2. You could instead define p & q to be the
average and p / q to be the minimum of p and q - whatever you wanted, or
whatever the standards body finds most mnemonic if you like.

As long as it was standardized, everyone would be on the same page.

That's (at least) the second time today you've accused someone of
being "deliberately obtuse" because they disagreed with you.

Yes, your proposal of adding multiple built-in overloaded operators
for pointers would be compatible with the current language; it
wouldn't break existing code. But using "/" for pointer average
would be confusing and would, in my opinion not provide enough
benefit to justify the costs. It's used rarely enough that, even
if it were standardized, typical programmers would likely not
recognize it. And even if it were added to the C201X standard,
we'd have to wait at least a decade before we could confidently
write code that depends on it.

Just because a certain operator symbol isn't used in a certain
context, that doesn't mean we *have* to define a meaning for it.
And brevity is not always a virtue. Or, if you prefer, @ brev \
virt ``. :cool:}
 
E

Eric Sosman

I think you are being deliberately obtuse here.

What's this, your new catch-phrase? "Use it three times
and it's yours?"
The point is that at present, if p and q are pointers, then p / q has no
meaning, so you lose nothing and gain some brevity by giving it a
meaning. I chose as an example defining "p / q" to be the average of p
and q, i.e. q - (q - p) / 2. You could instead define p& q to be the
average and p / q to be the minimum of p and q - whatever you wanted, or
whatever the standards body finds most mnemonic if you like.

As long as it was standardized, everyone would be on the same page.

While we're at it, let's define p+q to be "the maximum of p
and q," and "p^q" to be "whichever of p and q is non-null, or a
null pointer if both are null," and "p>>q" to be "a random number."

What I'm getting at with this ridicule is a point I've made
before and still believe important: Computer source code is written
to be read by two audiences, the compiler and other programmers.
Of these, the latter is by far the more important. Hence, silly
impediments to readability are counter-productive. Brevity is not
always the soul of wit -- or, how much APL have you read recently?
 
P

Phil Carmody

john said:
Hi

We know that C has been through several revisions since it was first
created by Kernigan and Richie. One thing I don't understand is why some
of the opportunities for expansion present in the original C
specification have not been taken up in these subsequent revisions.

Here are two examples.

1. C does not have a ||= operator (or for that matter a &&= operator).
This is extremely useful and elegant in Perl for specifying default
values and it could work just the same way in C.

It's an absolutely lousy method for specifying default values. If
you're using it that way, you're probably using it incorrectly.
2. There are lots of operations that we often need to perform on pointers
to the same block of memory, e.g. find the max or min, or the average of
them, and many others. There are also lots of arithmetic operations that
are not currently defined for pointers, in fact only minus (ptrdiff_t) is
defined. So why not extend the syntax so that unused operators like +,
*, /, %, ^, &, etc would implement these useful operations.

For example, if / was average then this would lead to simpler code like
johns_search(int *first, int *last)
{
int *mid = first / last;
...

instead of a complicated expression with lots of terms.

What's the 'average' of two pointers, even with the rider that
you want those pointers to be surrogates for blocks of memory?
How big are those blocks of memory? What are you doing with
two of them, normally you average a single set of data, not
two sets of data? The whole thing is an ill-conceived abomination.

Phil
 
P

Phil Carmody

Seebs said:
No it couldn't, because "a || b" in C yields true if either is not zero,
but in perl, it yields a if a is not zero, otherwise b.

$a || $b doesn't always yeild $a if $a is not zero, as it won't
yield $a if $a is the empty string or undefined. Perl's a bit too
flexible to be used as a basis.

Phil
 
P

Phil Carmody

john said:
Whatever. I don't have the book to hand to double check the spellings.


??

There's not one single clearly obvious interpretation for them.
If you have to arbitrarily fill in the gaps, then they add more
confusion to the language than they add expressivity.
I think you are being deliberately obtuse here.

It seems as if anything you can't grasp is 'obtuse'. As they're
perfectly correct, I would prefer posters of same didn't change
their deliberate-chosen posting style, as it contributes far more
to c.l.c than ill-grounded fantasies.
As ||= currently has no meaning, the standards body is free to assign it
any meaning it chooses - it doesn't *need* to be consistent with ||.

Bollocks.

Semantics

[#3] A compound assignment of the form E1 op= E2 differs
from the simple assignment expression E1 = E1 op (E2) only
in that the lvalue E1 is evaluated only once.

Phil
 
S

Seebs

$a || $b doesn't always yeild $a if $a is not zero, as it won't
yield $a if $a is the empty string or undefined. Perl's a bit too
flexible to be used as a basis.

Yeah, I was oversimplifying. My bad.

I prefer Ruby and Lua, in which unset and false are treated as false, and
0 and empty strings are not, because those are non-false values. C really
has to have 0 be "false", at the level it works at, but for higher-level
things, I much prefer the distinction to be "false" vs. "things which are not
false".

-s
 

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,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top