Discussion:
If statement with initializer
(too old to reply)
Thiago Adams
2017-05-10 13:29:33 UTC
Permalink
Raw Message
C++ 17, has now a new if.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html

if ( for-init-statement condition ) statement

is equivalent to

{
for-init-statement
if ( condition ) statement
}

and

if ( for-init-statement condition ) statement else statement

is equivalent to

{
for-init-statement
if ( condition ) statement else statement
}

Would you like to see this if on C?
David Brown
2017-05-10 13:42:22 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
and
if ( for-init-statement condition ) statement else statement
is equivalent to
{
for-init-statement
if ( condition ) statement else statement
}
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.

In C++17, you can now write:

if (bool b = foo(); b) ...

as equivalent to:

{
bool b = foo();
if (b) ...
}

(Note the critical extra set of brackets.)

I think it would have been much nice if it had been simply:

if (bool b = foo()) ...


I would not mind if this came to C, but I think it is unlikely. The
change is useful in C++ because you sometimes want precise control of
when a variable goes out of scope and lifetime, and therefore gets
destroyed. In C, nothing special happens when a local variable goes out
of scope, so it matters little if its scope and lifetime is extended.
At most, it would be a syntactic convenience allowing you to re-use the
same identifier without using new sets of brackets.
Ben Bacarisse
2017-05-10 14:36:25 UTC
Permalink
Raw Message
David Brown <***@hesbynett.no> writes:
<snip>
Post by David Brown
Post by Thiago Adams
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
<snip>
Post by David Brown
Post by Thiago Adams
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
But that would not serve all the intended purposes:

if (int n = expensive(); 2 < x && x < 17) ...
--
Ben.
David Brown
2017-05-10 15:23:41 UTC
Permalink
Raw Message
Post by Ben Bacarisse
<snip>
Post by David Brown
Post by Thiago Adams
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
<snip>
Post by David Brown
Post by Thiago Adams
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
if (int n = expensive(); 2 < x && x < 17) ...
I assume you meant to write "if (int x = expensive(); 2 < x && x < 17)".

And in C++, you might well have a class object in the initialiser and
want to apply a method to it.

Yes, the second clause is sometimes needed - but often it is not, and I
think it would be nice if it were optional.
Ben Bacarisse
2017-05-10 15:40:37 UTC
Permalink
Raw Message
David Brown <***@hesbynett.no> writes:
<snip>
Post by David Brown
Yes, the second clause is sometimes needed - but often it is not, and I
think it would be nice if it were optional.
I misunderstood. I thought you didn't want it at all. Sorry.
--
Ben.
David Brown
2017-05-10 20:22:29 UTC
Permalink
Raw Message
Post by Ben Bacarisse
<snip>
Post by David Brown
Yes, the second clause is sometimes needed - but often it is not, and I
think it would be nice if it were optional.
I misunderstood. I thought you didn't want it at all. Sorry.
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
So I expressed myself rather badly there.

You have to listen to what I /mean/, not what I /say/ :-)
Manfred
2017-05-13 15:15:33 UTC
Permalink
Raw Message
Post by David Brown
Post by Ben Bacarisse
<snip>
Post by David Brown
Post by Thiago Adams
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
<snip>
Post by David Brown
Post by Thiago Adams
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
if (int n = expensive(); 2 < x && x < 17) ...
I assume you meant to write "if (int x = expensive(); 2 < x && x < 17)".
And in C++, you might well have a class object in the initialiser and
want to apply a method to it.
Yes, the second clause is sometimes needed - but often it is not, and I
think it would be nice if it were optional.
I tend to agree with you on the point, with a couple of extra remarks:

I make extensive use of declarations in clause-1 of for loops (sometimes
I even miss the possibility of declaring variables of different type in
there), so by extension a similar feature in the if statement could be
useful - I like tight scope control.

But there are at least two remarkable differences WRT the for statement
I see:
- A declaration fits nicely within clause-1 of the for loop, because it
has always been ;-delimited. This is not true for if and while
statements, so I see it as a decrease in clarity of these statements.
Maybe it is because I am used to the old notation, anyway your proposal
of having the second clause optional is a plus in this respect.

- In case of an if(int x = ...){...} else{...} statement, the scope of
variable x would be /both/ the if {} block /and/ the else{} block, which
is also less clear than the established habit of having variable scope
within single block.

From both respects if I read the construct already available as of now:
{
int n = foo();
if(n > 12)
{
// use n
}
else
{
// use n
}
}

I doubt that it can be improved by the proposed addition.

Still I am with you if I would read or write:
if(int n = bar()) // meaning if n is nonzero
{
// use n
}

But it would be very specific, and I doubt if the lack of generality
would allow for making into a standard.
Patrick.Schluter
2017-05-13 19:13:18 UTC
Permalink
Raw Message
Post by Manfred
Post by David Brown
Post by Ben Bacarisse
<snip>
Post by David Brown
Post by Thiago Adams
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
<snip>
Post by David Brown
Post by Thiago Adams
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
if (int n = expensive(); 2 < x && x < 17) ...
I assume you meant to write "if (int x = expensive(); 2 < x && x < 17)".
And in C++, you might well have a class object in the initialiser and
want to apply a method to it.
Yes, the second clause is sometimes needed - but often it is not, and I
think it would be nice if it were optional.
I make extensive use of declarations in clause-1 of for loops (sometimes
I even miss the possibility of declaring variables of different type in
there), so by extension a similar feature in the if statement could be
useful - I like tight scope control.
But there are at least two remarkable differences WRT the for statement
- A declaration fits nicely within clause-1 of the for loop, because it
has always been ;-delimited. This is not true for if and while
statements, so I see it as a decrease in clarity of these statements.
Maybe it is because I am used to the old notation, anyway your proposal
of having the second clause optional is a plus in this respect.
- In case of an if(int x = ...){...} else{...} statement, the scope of
variable x would be /both/ the if {} block /and/ the else{} block, which
is also less clear than the established habit of having variable scope
within single block.
{
int n = foo();
if(n > 12)
{
// use n
}
else
{
// use n
}
}
I doubt that it can be improved by the proposed addition.
if(int n = bar()) // meaning if n is nonzero
{
// use n
}
Here it starts to become difficult because of the order of precedence
rules of comparisons

if(int n = bar() == 4) // what does it mean?
or
if(int n = (bar() == 4)) // With the current order, doesn't make much sense
or
if(int (n = bar()) == 4) // Syntax error but would be what we want
or
if((int n = bar()) == 4) // opens the can of worms of declarations in
expressions

I suppose the C++ commitee introduced the ; clause because of that.
Ben Bacarisse
2017-05-13 19:40:23 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Manfred
Post by David Brown
Post by Ben Bacarisse
<snip>
Post by David Brown
Post by Thiago Adams
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
<snip>
Post by David Brown
Post by Thiago Adams
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
if (int n = expensive(); 2 < x && x < 17) ...
I assume you meant to write "if (int x = expensive(); 2 < x && x < 17)".
And in C++, you might well have a class object in the initialiser and
want to apply a method to it.
Yes, the second clause is sometimes needed - but often it is not, and I
think it would be nice if it were optional.
I make extensive use of declarations in clause-1 of for loops (sometimes
I even miss the possibility of declaring variables of different type in
there), so by extension a similar feature in the if statement could be
useful - I like tight scope control.
But there are at least two remarkable differences WRT the for statement
- A declaration fits nicely within clause-1 of the for loop, because it
has always been ;-delimited. This is not true for if and while
statements, so I see it as a decrease in clarity of these statements.
Maybe it is because I am used to the old notation, anyway your proposal
of having the second clause optional is a plus in this respect.
- In case of an if(int x = ...){...} else{...} statement, the scope of
variable x would be /both/ the if {} block /and/ the else{} block, which
is also less clear than the established habit of having variable scope
within single block.
{
int n = foo();
if(n > 12)
{
// use n
}
else
{
// use n
}
}
I doubt that it can be improved by the proposed addition.
if(int n = bar()) // meaning if n is nonzero
{
// use n
}
Here it starts to become difficult because of the order of precedence
rules of comparisons
if(int n = bar() == 4) // what does it mean?
There's really no issue of precedence here. Only == and the () of the
function call can be called operators. The rest of the symbols are
"punctuation" used in the syntax for other things.

This is not to say that there is no possibility of confusion. People
confuse ',' used as an operator and ',' used as punctuation in, say, a
function call, so they may also confuse '=' used as an operator and '='
when used as punctuation in a declaration. Precedence only kicks in when
both the == and the = are operators.

As it happens, there is already scope for such confusion because
declarations can include commas:

int x = 1, b = 2;

This line has, despite appearances, no operators at all and so
precedence can't be used to explain anything about it!

David's proposal is just let

if (T v = <exp>) ...

be the same as C++ defines

if (T v = <exp>; <exp>)

(except that <exp> is evaluated only once) or maybe he intended it to be
the same as

if (T x = <exp>; v)

(They are not always going to be the same.)

<snip>
--
Ben.
Patrick.Schluter
2017-05-13 20:30:42 UTC
Permalink
Raw Message
Post by Ben Bacarisse
This line has, despite appearances, no operators at all and so
precedence can't be used to explain anything about it!
David's proposal is just let
if (T v = <exp>) ...
The limitation here is that only the boolean (false, true) evaluation of
the the expression is done here. This is too limiting and problematic,
as often one wants to combine with comparison operators (==, <, <= >=,
!=) and logic expressions &&, ||.

if( int v = getc() == 'A' || v == 'B') ...

doesn't work. So the C++ committee did the right thing imho. The ; adds
a sequence point, allows to use the same grammar elements for
declaration with initializer and boolean expression that is used elsewhere.
I googled a bit around and my objections above seem to be exactly the
reason why they introduced the statement separator in C++17.
Post by Ben Bacarisse
be the same as C++ defines
if (T v = <exp>; <exp>)
if( int v = getc(); v == 'A' || v == 'B') ...
Post by Ben Bacarisse
(except that <exp> is evaluated only once) or maybe he intended it to be
the same as
if (T x = <exp>; v)
(They are not always going to be the same.)
<snip>
Ben Bacarisse
2017-05-13 21:01:16 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Ben Bacarisse
This line has, despite appearances, no operators at all and so
precedence can't be used to explain anything about it!
David's proposal is just let
if (T v = <exp>) ...
The limitation here is that only the boolean (false, true) evaluation
of the the expression is done here.
Yes, but he suggested it as an extra -- a simplified version for when it
does work.

<snip>
--
Ben.
David Brown
2017-05-14 14:20:02 UTC
Permalink
Raw Message
Post by Ben Bacarisse
David's proposal is just let
if (T v = <exp>) ...
be the same as C++ defines
if (T v = <exp>; <exp>)
(except that <exp> is evaluated only once) or maybe he intended it to be
the same as
if (T x = <exp>; v)
(They are not always going to be the same.)
<snip>
My thought was that:

if (T v = <exp>) ...

be the same as

if (T v = <exp>; v) ...


It seems likely that the C++ folks have already thought about that, and
concluded that it is a bad idea (perhaps for the reasons given in this
sub-thread, perhaps for other reasons as well).
Manfred
2017-05-13 15:24:45 UTC
Permalink
Raw Message
Post by Ben Bacarisse
<snip>
Post by David Brown
Post by Thiago Adams
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
<snip>
Post by David Brown
Post by Thiago Adams
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
In the specific case of a bool variable b would be known to be true
inside the body of the statement, so there would be no need to declare
an identifier for it.
Post by Ben Bacarisse
if (int n = expensive(); 2 < x && x < 17) ...
And in turn this unnicely resembles a tweaked for loop:
for(int n = expensive(); 2 < n && n < 17; )
{
// use n
// do stuff
break;
}
(uniquely from a readability point of view)
Philip Lantz
2017-05-14 23:10:19 UTC
Permalink
Raw Message
Post by David Brown
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
and
if ( for-init-statement condition ) statement else statement
is equivalent to
{
for-init-statement
if ( condition ) statement else statement
}
Would you like to see this if on C?
I would rather see it in a manner that does not need the extra clause -
or at least, the extra clause should be optional.
if (bool b = foo(); b) ...
{
bool b = foo();
if (b) ...
}
(Note the critical extra set of brackets.)
if (bool b = foo()) ...
This syntax has already been supported since C++ 11.
Thiago Adams
2017-05-10 13:44:02 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Post by Thiago Adams
Would you like to see this if on C?
(switch also receive this upgrade)

Adding more ...

C++ 17 also have news on preprocessor.

__has_include

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0061r0.html

And a new assert with no message

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3928.pdf

static_assert ( constant-expression ) ;

One more:

Deprecate ++ on bool. (this could be applied to _Bool)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0002r1.html


Would you like to see these features on C?
David Brown
2017-05-10 14:38:41 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Post by Thiago Adams
Would you like to see this if on C?
(switch also receive this upgrade)
Adding more ...
C++ 17 also have news on preprocessor.
__has_include
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0061r0.html
Personally, I have no use for that. If I want to include a file, I do -
I don't have use-cases myself for files that might or might not be
available. If other people see it as a useful feature, that's fine.
Post by Thiago Adams
And a new assert with no message
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3928.pdf
static_assert ( constant-expression ) ;
That makes a lot of sense to me, and is a feature I would use.
Sometimes I want my static assertions to have explicit messages, but
more often it would be neater and shorter to have a simple failure message.
Post by Thiago Adams
Deprecate ++ on bool. (this could be applied to _Bool)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0002r1.html
I can't see any use for incrementing bool's (nor for many other
operators). So I see no problem in deprecating bool ++. However, other
people might have written code that uses it, and changes to C need to be
very conservative about breaking something that worked before.
Post by Thiago Adams
Would you like to see these features on C?
GOTHIER Nathan
2017-05-10 14:22:15 UTC
Permalink
Raw Message
On Wed, 10 May 2017 06:29:33 -0700 (PDT)
Post by Thiago Adams
Would you like to see this if on C?
No because C shouldn't deserve to be as bloated as C++. Once more Bjarne
STROUSTRUP has soiled the C name with his counterfeit language that should have
been named the STROUSTRUP language instead of C++ to trick new programmers with
bad concepts.
Thiago Adams
2017-05-10 14:29:57 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Wed, 10 May 2017 06:29:33 -0700 (PDT)
Post by Thiago Adams
Would you like to see this if on C?
No because C shouldn't deserve to be as bloated as C++. Once more Bjarne
STROUSTRUP has soiled the C name with his counterfeit language that should have
been named the STROUSTRUP language instead of C++ to trick new programmers with
bad concepts.
Probably you are against the previous insertions at C as well, like _Staticassert and _Bool.
Am I right?
The language become bigger after that.
GOTHIER Nathan
2017-05-10 15:40:16 UTC
Permalink
Raw Message
On Wed, 10 May 2017 07:29:57 -0700 (PDT)
Post by Thiago Adams
Probably you are against the previous insertions at C as well, like _Staticassert and _Bool.
Am I right?
The language become bigger after that.
It is not a matter of size but conciseness.

That's why some programmers prefer C to the STROUSTRUP language.

Stacking flawed concepts doesn't make a good language. Likewise the nouveauté
is not synonym of efficiency and at some point the programmer have to use his
neurons to write good softwares.
s***@casperkitty.com
2017-05-10 15:48:54 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
Would you like to see this if on C?
What would be the effect of:

typedef struct { int x; } foo;

extern void actOnFoo(foo *p);
extern void someFunction(void);

void test()
{
foo *p;
p = (foo*){1};
if (int temp = someFunction())
p = (foo*){temp};
actOnFoo(p);
}

If "temp" had been declared prior to the "if" within the outer scoping block,
the lifetime of the compound literal within the "if" statement would extend
to the end of the function. Adding a scoping block to contain "temp" would
limit the lifetime of the compound literal to that of "temp".

Personally, I think the lifetime rules for compound literals are silly, and
the lifetime should extend either until code exits the *function* wherein a
literal is defined or execution re-reaches the point where it is created
(whereupon the lifetime of the original would end, and that of a new compound
literal would begin), but with the rules as they are anything that would
implicitly add a new scoping block should be considered dangerous.
David Brown
2017-05-10 20:24:51 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
Would you like to see this if on C?
typedef struct { int x; } foo;
extern void actOnFoo(foo *p);
extern void someFunction(void);
void test()
{
foo *p;
p = (foo*){1};
if (int temp = someFunction())
p = (foo*){temp};
actOnFoo(p);
}
What effect are you looking for? A compiler error? A failed code review?
s***@casperkitty.com
2017-05-10 20:29:51 UTC
Permalink
Raw Message
Post by David Brown
Post by s***@casperkitty.com
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
Would you like to see this if on C?
typedef struct { int x; } foo;
extern void actOnFoo(foo *p);
extern void someFunction(void);
void test()
{
foo *p;
p = &(foo){1};
if (int temp = someFunction())
p = &(foo){temp};
actOnFoo(p);
}
What effect are you looking for? A compiler error? A failed code review?
I slightly oopsed the syntax [hopefully corrected above]--basically the
question is whether declaring a variable within an "if" condition would
shorten the lifetime of a compound literal object used within the
controlled statement, so it ends at the end of the controlled statement
rather than at the end of the enclosing block.
David Brown
2017-05-10 21:27:39 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by David Brown
Post by s***@casperkitty.com
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
Would you like to see this if on C?
typedef struct { int x; } foo;
extern void actOnFoo(foo *p);
extern void someFunction(void);
void test()
{
foo *p;
p = &(foo){1};
if (int temp = someFunction())
p = &(foo){temp};
actOnFoo(p);
}
What effect are you looking for? A compiler error? A failed code review?
I slightly oopsed the syntax [hopefully corrected above]--basically the
(Please do not change quoted parts of a post - it makes it very hard to
follow. And you are still assigning the result of a void function to an
int.)
Post by s***@casperkitty.com
question is whether declaring a variable within an "if" condition would
shorten the lifetime of a compound literal object used within the
controlled statement, so it ends at the end of the controlled statement
rather than at the end of the enclosing block.
I believe the "if" statement now makes a new block - it acts as though
it were surrounded by brackets.
Thiago Adams
2017-05-10 16:40:20 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
and
if ( for-init-statement condition ) statement else statement
is equivalent to
{
for-init-statement
if ( condition ) statement else statement
}
Would you like to see this if on C?
These samples look good for me:


if (Box* pBox = Shape_As_Box(pShape), pBox)
{
//pBox ...
}


if (FILE* file = fopen(""), file)
{
//file...
fclose(file);
}

if (Type* p = malloc(sizeof * p), p)
{
}
Ben Bacarisse
2017-05-10 18:15:49 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
<snip>
Post by Thiago Adams
Post by Thiago Adams
Would you like to see this if on C?
if (Box* pBox = Shape_As_Box(pShape), pBox)
{
//pBox ...
}
Are deliberately making it different to the C++ form or was the comma a
typo?

<snip>
--
Ben.
Thiago Adams
2017-05-10 18:22:53 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
<snip>
Post by Thiago Adams
Post by Thiago Adams
Would you like to see this if on C?
if (Box* pBox = Shape_As_Box(pShape), pBox)
{
//pBox ...
}
Are deliberately making it different to the C++ form or was the comma a
typo?
The comma was my mistake.
bartc
2017-05-10 17:06:30 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
and
if ( for-init-statement condition ) statement else statement
is equivalent to
{
for-init-statement
if ( condition ) statement else statement
}
Would you like to see this if on C?
Not me. I prefer declarations all tucked away in a corner so they don't
clutter up the code.

People complain about Hungarian notation but this doesn't seem much
different.

Besides, this can be done now with {} either surrounding the if
statement (assuming the scope extends to the end of the second
statement), or inside the condition using the gcc extension.
--
bartc
Ben Bacarisse
2017-05-10 18:19:59 UTC
Permalink
Raw Message
Post by bartc
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
and
if ( for-init-statement condition ) statement else statement
is equivalent to
{
for-init-statement
if ( condition ) statement else statement
}
Would you like to see this if on C?
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.

<snip>
--
Ben.
bartc
2017-05-10 19:19:28 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it might
have been declared somewhere in between.

Here's one example: https://pastebin.com/iVtbFN2U where most names are
declared at the start, but some are defined in situ which means you
can't just immediately go to the top and see a cast list of all the names.

Here's another example: https://pastebin.com/v4h6Aabx where nothing is
declared at the top other than parameter names.

And it uses one of those styles where variable names all tend to look
alike. But some of them are actually identical, which you don't know
until you've scanned the entire function (there are two zWhere's for
example, fortunately of the same type).
--
bartc
Thiago Adams
2017-05-10 20:21:02 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it might
have been declared somewhere in between.
Do you mean
int i;
if ()
{
int i; //like this ??
}
Ben Bacarisse
2017-05-10 21:16:55 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.

It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
that come to mind:

Smaller scope tend to reduce the use of either indeterminate objects
or objects initialised with meaningless "place-holder" values.

They localise changes. If I alter the upper bound (or otherwise alter
the exit) of

for (int i = lo; i < f(lo); i++) result = g(i, result);

I know I can't be messing with any code that has assumed that i == f(lo)
below the loop.

This is most problematic when multiple people edit the code. With i
declared "up top" they may assume the value after the loop is deliberate
assured.

In effect you are able to write inline functions with some of the
encapsulation benefits the functions give you, without the limitations
of C's functions.
Post by bartc
Here's one example: https://pastebin.com/iVtbFN2U where most names are
declared at the start, but some are defined in situ which means you
can't just immediately go to the top and see a cast list of all the names.
Here's another example: https://pastebin.com/v4h6Aabx where nothing is
declared at the top other than parameter names.
And it uses one of those styles where variable names all tend to look
alike. But some of them are actually identical, which you don't know
until you've scanned the entire function (there are two zWhere's for
example, fortunately of the same type).
I don't know what I am to take form these examples.
--
Ben.
David Brown
2017-05-10 21:31:25 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by bartc
Here's one example: https://pastebin.com/iVtbFN2U where most names are
declared at the start, but some are defined in situ which means you
can't just immediately go to the top and see a cast list of all the names.
Here's another example: https://pastebin.com/v4h6Aabx where nothing is
declared at the top other than parameter names.
And it uses one of those styles where variable names all tend to look
alike. But some of them are actually identical, which you don't know
until you've scanned the entire function (there are two zWhere's for
example, fortunately of the same type).
I don't know what I am to take form these examples.
As the saying in Norwegian goes, you are supposed to choose between the
plague or cholera.
bartc
2017-05-10 21:50:29 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.
I don't want to have to use tools just to understand code. (Otherwise
what's the point of a language having syntax? Just use some internal
format for source code, and rely on a tool for rendering in a syntax and
style of your choice.)
Post by Ben Bacarisse
It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
Smaller scope tend to reduce the use of either indeterminate objects
or objects initialised with meaningless "place-holder" values.
What happened to all the people telling us to keep functions to ten
lines or less? Then having multiple scopes within such a span would be
ludicrous.
Post by Ben Bacarisse
They localise changes. If I alter the upper bound (or otherwise alter
the exit) of
for (int i = lo; i < f(lo); i++) result = g(i, result);
I know I can't be messing with any code that has assumed that i == f(lo)
below the loop.
That's probably the only example where a localised loop index name can
make sense. In fact, here such a local index name is desirable, so you
don't even want to bother declaring it. [Not practical in C as there is
no official concept of a loop index variable]
Post by Ben Bacarisse
In effect you are able to write inline functions with some of the
encapsulation benefits the functions give you, without the limitations
of C's functions.
I don't get that. The local names in any function are already
encapsulated; it doesn't need further nested scopes, and it doesn't
matter if the function is inlined or not, as the local names will never
clash with any names at the call-site where it might be inlined.
Post by Ben Bacarisse
Post by bartc
Here's one example: https://pastebin.com/iVtbFN2U where most names are
Here's another example: https://pastebin.com/v4h6Aabx where nothing is
I don't know what I am to take form these examples.
It shows the practical problems of looking at a line of code and trying
to locate the corresponding declarations. When the declarations can be
anywhere within a function, and the same variable name is overloaded.
--
bartc
Ben Bacarisse
2017-05-11 00:15:59 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.
I don't want to have to use tools just to understand code.
That's up to you but then you don't get any tools to help you see when
in this 300-line function i is mentioned. Both strategies have
Post by bartc
(Otherwise what's the point of a language having syntax? Just use some
internal format for source code, and rely on a tool for rendering in a
syntax and style of your choice.)
Post by Ben Bacarisse
It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
Smaller scope tend to reduce the use of either indeterminate objects
or objects initialised with meaningless "place-holder" values.
What happened to all the people telling us to keep functions to ten
lines or less? Then having multiple scopes within such a span would be
ludicrous.
Oh, sure. If your functions are small your scopes are small and then
every is happy, yes? I want small scopes not some particular for-loop
syntax. It's not always easy in C, because functions don't nest, but
where you can do it, it's the perfect strategy to get small scopes.

And you get the added advantage that you can have declarations anywhere
you like because, in a ten line function, you in your tool-less state
will still be able to find a declaration. In effect the issue
evaporates in languages where tiny functions are the norm.
Post by bartc
Post by Ben Bacarisse
They localise changes. If I alter the upper bound (or otherwise alter
the exit) of
for (int i = lo; i < f(lo); i++) result = g(i, result);
I know I can't be messing with any code that has assumed that i == f(lo)
below the loop.
That's probably the only example where a localised loop index name can
make sense. In fact, here such a local index name is desirable, so you
don't even want to bother declaring it. [Not practical in C as there
is no official concept of a loop index variable]
Obviously I disagree about this being the only case, but at least
there's one thing we do agree on. In fact two things: very short
functions and local for-loop declarations.

<snip>
Post by bartc
It shows the practical problems of looking at a line of code and
trying to locate the corresponding declarations. When the declarations
can be anywhere within a function, and the same variable name is
overloaded.
Sure. And they both illustrate the other problem of knowing where code
is making what assumptions about the values in these quasi-global
variables.
--
Ben.
bartc
2017-05-11 13:15:24 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by bartc
What happened to all the people telling us to keep functions to ten
lines or less? Then having multiple scopes within such a span would be
ludicrous.
Oh, sure. If your functions are small your scopes are small and then
every is happy, yes? I want small scopes not some particular for-loop
syntax. It's not always easy in C, because functions don't nest, but
where you can do it, it's the perfect strategy to get small scopes.
And you get the added advantage that you can have declarations anywhere
you like because, in a ten line function, you in your tool-less state
will still be able to find a declaration. In effect the issue
evaporates in languages where tiny functions are the norm.
Then you will need special tools to find where all the functions are!

(Actually, my own language has nested functions (which I've never used),
partly through not bothering to prohibit them.

And it not only allows declarations anywhere (again by not enforcing a
boundary between them and statements), but they can be out-of-order. So
you could declare all your local variables at the end of a function if
you want!

[Not practical in C as it would require an extra pass, which I need
anyway to allow out-of-order functions and to eliminate forward
declarations of functions.]

However, it doesn't suffer so much from the same issues as C, as there
are no block-scopes, and any local name can only be declared once. So
once you've found the declaration, you can stop looking.

Furthermore, as code develops and blocks are added and removed, or a
name starts being used before its declaration, it's not necessary to
keep re-locating declarations to ensure a name is always declared before
use. [In C, a name might inadvertently be resolved to a more global one
if its declaration occurs later.])
--
bartc
s***@casperkitty.com
2017-05-11 15:17:08 UTC
Permalink
Raw Message
Post by bartc
And it not only allows declarations anywhere (again by not enforcing a
boundary between them and statements), but they can be out-of-order. So
you could declare all your local variables at the end of a function if
you want!
A lot of programs have a usage pattern that, for accurate description, would
require more control over scope/lifetime than C supports. For example, in
something like:

double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);

If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it, but if scoping braces were used to end the scope of dx and dy they
would also end the scope of distance. Aside from the chicken-and-egg
problems of allowing programmers to use a new syntax without limiting the
range of tools they can use, perhaps it might be helpful to add an
"extern auto" qualifier which would cause an object declaration to take
effect in the enclosing scope, thus allowing:

{
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
extern auto double distance = sqrt(dx*dx+dy*dy);
extern auto double angle = atan2(dy,dx);
}

to create variables for use in the enclosing scope. An additional helpful
feature would be to say that an "extern auto" declaration without an
initialization would pass an already-declared block-local variable (which
might have been exported from an inner block) to the enclosing scope.

Most of the places where I've seen objects get declared mid-block would be
better accommodated by adding additional scoping blocks, if there were a
way to export variables from within them.
bartc
2017-05-11 18:00:06 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by bartc
And it not only allows declarations anywhere (again by not enforcing a
boundary between them and statements), but they can be out-of-order. So
you could declare all your local variables at the end of a function if
you want!
A lot of programs have a usage pattern that, for accurate description, would
require more control over scope/lifetime than C supports. For example, in
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);
If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it,
Why? If they really are used nowhere else, then a smart compiler will
know that.

This doesn't seem to happen anywhere else, as at file-scope for example:
you declare functions g() and h() which are only used by f(); but g()
and h() stay available for the rest of the file.

I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case variations).

Outside a function, there are fewer possibilities: namely one for each
identifier. Despite the span of code being far bigger (an entire module
for local names, the entire program for global ones).

So it's unbalanced; we don't need even finer divisions of the namespace
inside a function or a block!
--
bartc
s***@casperkitty.com
2017-05-11 18:49:28 UTC
Permalink
Raw Message
Post by bartc
Post by s***@casperkitty.com
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);
If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it,
Why? If they really are used nowhere else, then a smart compiler will
know that.
Sure the compiler will know it, but if code needs to use similar temporary
variables more than once, it will be necessary to either change the second
usage from a declaration to an assignment, add a standalone declaration and
change both usages to assignment, or tweak the second usage to use different
names from the first. By contrast, if the scopes were limited, then such
issues would be avoided.

In cases involving pointers, limiting variable scope would have other
advantages as well. Consider:

rectangle *rp = &someObject->bounds;
double objectX = (rp->left+rp->right) / 2;
double objectX = (rp->top+rp->bottom) / 2;
...
someObject = realloc(someObject, newSize);
if (!someObject) fatal_error();
...

Code like the above would leave a dangling pointer in scope. If rp
isn't going to be used after the computations of objectX and objectY,
the fact that it's left dangling after the realloc() would course be
no big deal, but if it rp is going to be used later on, it would be
necessary to reload it with &someObject->bounds. Expressly limiting
the scope would make it clear to anyone reading the code that there
was no dangling pointer "rp" since there would be no pointer "rp".
Post by bartc
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case variations).
Those don't help if the *purpose* of a temporary variable is to set the
initialization value for something else, since ending the scope of the
temporaries would imply ending the scope of anything initialized therewith.
bartc
2017-05-11 19:51:05 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by bartc
Post by s***@casperkitty.com
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);
If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it,
Why? If they really are used nowhere else, then a smart compiler will
know that.
Sure the compiler will know it, but if code needs to use similar temporary
variables more than once, it will be necessary to either change the second
usage from a declaration to an assignment, add a standalone declaration and
change both usages to assignment, or tweak the second usage to use different
names from the first. By contrast, if the scopes were limited, then such
issues would be avoided.
In cases involving pointers, limiting variable scope would have other
rectangle *rp = &someObject->bounds;
double objectX = (rp->left+rp->right) / 2;
double objectX = (rp->top+rp->bottom) / 2;
...
someObject = realloc(someObject, newSize);
if (!someObject) fatal_error();
...
Code like the above would leave a dangling pointer in scope. If rp
isn't going to be used after the computations of objectX and objectY,
the fact that it's left dangling after the realloc() would course be
no big deal, but if it rp is going to be used later on, it would be
necessary to reload it with &someObject->bounds.
This is general problem with using pointers in C programs.

When you have, say, a large tree full of pointers to elements of a
dynamic array, and you resize the array resulting in a new base address,
then all the thousands of pointers will be out of date.

By contrast, all non-static variables in functions should be considered
to be temporary working variables. Maybe you will detect the odd bug by
using the minimal possible scope envelope for each, but it's more likely
to make more work trying to program with and around such practices.
Lifetimes won't be in nice nested scopes but will overlap.


(This sounds a bit like the strict hierarchical import system on one of
my languages. It's hard to structure things to avoid mutual/circular
imports, and it restricts compilation order.

The next compiler will drop restrictions and life much easier.)
Post by s***@casperkitty.com
Post by bartc
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case variations).
Those don't help if the *purpose* of a temporary variable is to set the
initialization value for something else, since ending the scope of the
temporaries would imply ending the scope of anything initialized therewith.
How about a special temporary variable, perhaps starting with "$", that
can only be used once? Your examples use them twice, meaning two
variables to replace rp for example. However source then starts to look
some compiler's intermediate code. HLLs are supposed to make life
simpler and take care of such details.
--
bartc
Ian Collins
2017-05-12 08:02:00 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by bartc
Post by s***@casperkitty.com
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);
If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it,
Why? If they really are used nowhere else, then a smart compiler will
know that.
Sure the compiler will know it, but if code needs to use similar temporary
variables more than once, it will be necessary to either change the second
usage from a declaration to an assignment, add a standalone declaration and
change both usages to assignment, or tweak the second usage to use different
names from the first. By contrast, if the scopes were limited, then such
issues would be avoided.
If the function were a sensible length, such issues would be avoided.
--
Ian
Robert Wessel
2017-05-12 07:01:02 UTC
Permalink
Raw Message
Post by bartc
Post by s***@casperkitty.com
Post by bartc
And it not only allows declarations anywhere (again by not enforcing a
boundary between them and statements), but they can be out-of-order. So
you could declare all your local variables at the end of a function if
you want!
A lot of programs have a usage pattern that, for accurate description, would
require more control over scope/lifetime than C supports. For example, in
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);
If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it,
Why? If they really are used nowhere else, then a smart compiler will
know that.
you declare functions g() and h() which are only used by f(); but g()
and h() stay available for the rest of the file.
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case variations).
Outside a function, there are fewer possibilities: namely one for each
identifier. Despite the span of code being far bigger (an entire module
for local names, the entire program for global ones).
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
Post by bartc
So it's unbalanced; we don't need even finer divisions of the namespace
inside a function or a block!
This is really a bit of a tempest in a teapot. Smaller scopes within
a function is neither complicated for a compiler to implement, nor for
the programmer to understand. On the flip side, with reasonably sized
functions, the smaller scope only offers small advantages. OTOH, if
you have functions big enough that you *need* to reduce the scope of
variables, it's probably time to consider making them smaller.
Tim Rentsch
2017-05-13 15:54:12 UTC
Permalink
Raw Message
Post by Robert Wessel
Post by bartc
[...]
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case variations).
Outside a function, there are fewer possibilities: namely one for each
identifier. Despite the span of code being far bigger (an entire module
for local names, the entire program for global ones).
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
I'm curious to know what sort of items you envision putting in
those classes. For all the examples I have thought of it seems
of little practical value or there is a straightforward way of
accomplishing the same goal without needing any extensions. What
are your use cases?
bartc
2017-05-13 16:45:23 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Robert Wessel
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
I'm curious to know what sort of items you envision putting in
those classes. For all the examples I have thought of it seems
of little practical value or there is a straightforward way of
accomplishing the same goal without needing any extensions. What
are your use cases?
Lightweight classes can just be structs, but with the ability to define
more things inside them other than just members:

* Typedefs
* Enums
* Structs (in a form that can be used from outside)
* Variables [static, to distinguish from normal members]
* Functions
* Nested classes

They would automatically provide a namespace mechanism. It would be
possible to access resources defined inside the class using the name of
the class; no instance of it is needed.

Example for enums:

class lights { enum {red, amber, green};};
class rgb { enum {red, green, blue};}'

Then they are used as lights.green or rgb.green. At the moment, the two
greens can't co-exist; you'd need to use the cruder lights_green and
rgb_green.

This can be taken a little further if instances are allowed (requiring
some normal members to be meaningful). But then it's harder to know when
to stop copying the other language. The above however doesn't present
many implementation problems and is easy to comprehend.
--
bartc
Tim Rentsch
2017-05-14 20:14:10 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Robert Wessel
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
I'm curious to know what sort of items you envision putting in
those classes. For all the examples I have thought of it seems
of little practical value or there is a straightforward way of
accomplishing the same goal without needing any extensions. What
are your use cases?
[...]
I saw these comments, just am holding off for now until I see
what Robert Wessel has to say.
Robert Wessel
2017-05-14 21:20:14 UTC
Permalink
Raw Message
On Sat, 13 May 2017 08:54:12 -0700, Tim Rentsch
Post by Tim Rentsch
Post by Robert Wessel
Post by bartc
[...]
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case variations).
Outside a function, there are fewer possibilities: namely one for each
identifier. Despite the span of code being far bigger (an entire module
for local names, the entire program for global ones).
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
I'm curious to know what sort of items you envision putting in
those classes. For all the examples I have thought of it seems
of little practical value or there is a straightforward way of
accomplishing the same goal without needing any extensions. What
are your use cases?
A major issue for large projects is namespace pollution. The ability
to bury most bits of a particular subsystem inside a class greatly
reduces that problem (leaving only the name of the class globally
visible). The ability to make items private further enhances
encapsulation.

Obviously you can put data items inside a struct in C, but not (in any
"good" way), functions (methods) intended to work on them.

Personally I find (large) programs consisting components with limited
and well defined interfaces to be much easier to understand than with
the "everything" visible approach, and make it much easier to be sure
of the integrity of the object in question. Obviously poorly designed
interfaces make a hash of that, but badly designed programs are just
badly designed programs.

This has some parallels to Dykstra's complaints about gotos. It was
not so much gotos themselves, but gotos running hither, thither and
yon over very large programs, leading to the "how did I get here?"
question. If the scope is limited to a single function (as it is in
many modern programming languages that support goto), it's something
of a non-issue unless your functions get excessively large. Similarly
with the "everything is visible" paradigm, the question is "how did
this get changed?".

My understanding of Bartc's comment was that he was complaining that
ever finer (less than function) scopes are somewhat pointless, while
ignoring any subdivision of the program or global namespaces, which
are arguably a much more pressing issue.

And I'm not saying that you can't do these things in C, but it tends
to be pretty manual.
Tim Rentsch
2017-05-15 02:14:34 UTC
Permalink
Raw Message
Post by Robert Wessel
On Sat, 13 May 2017 08:54:12 -0700, Tim Rentsch
Post by Tim Rentsch
Post by Robert Wessel
Post by bartc
[...]
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case
{} variations).
Outside a function, there are fewer possibilities: namely one for each
identifier. Despite the span of code being far bigger (an entire module
for local names, the entire program for global ones).
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
I'm curious to know what sort of items you envision putting in
those classes. For all the examples I have thought of it seems
of little practical value or there is a straightforward way of
accomplishing the same goal without needing any extensions. What
are your use cases?
A major issue for large projects is namespace pollution. The ability
to bury most bits of a particular subsystem inside a class greatly
reduces that problem (leaving only the name of the class globally
visible). The ability to make items private further enhances
encapsulation.
Obviously you can put data items inside a struct in C, but not (in any
"good" way), functions (methods) intended to work on them. [...]
So what you want is something along the lines of structs
with (private) data and functions that operate on the
data of the instance on which the function is invoked
(plus any other arguments, of course)? Is that all
or is there something more? Constructors? Destructors?
Copy assignment? Move assignment? References? I'm
trying to understand where you mean to draw the line.

(I assume throw/catch is meant to be on your list of 'not's
along with inheritance, etc.)
Robert Wessel
2017-05-15 02:54:15 UTC
Permalink
Raw Message
On Sun, 14 May 2017 19:14:34 -0700, Tim Rentsch
Post by Tim Rentsch
Post by Robert Wessel
On Sat, 13 May 2017 08:54:12 -0700, Tim Rentsch
Post by Tim Rentsch
Post by Robert Wessel
Post by bartc
[...]
I think there are already enough possibilities for scope inside
functions (so an infinite number of versions of the same identifier can
be used, and if that's not enough, you can use upper/lower case
{} variations).
Outside a function, there are fewer possibilities: namely one for each
identifier. Despite the span of code being far bigger (an entire module
for local names, the entire program for global ones).
C++ classes provide an excellent intermediate scope for items. If
there were a major feature of C++ I'd want in C, it would be classes
(not inherence, overloading, templates...).
I'm curious to know what sort of items you envision putting in
those classes. For all the examples I have thought of it seems
of little practical value or there is a straightforward way of
accomplishing the same goal without needing any extensions. What
are your use cases?
A major issue for large projects is namespace pollution. The ability
to bury most bits of a particular subsystem inside a class greatly
reduces that problem (leaving only the name of the class globally
visible). The ability to make items private further enhances
encapsulation.
Obviously you can put data items inside a struct in C, but not (in any
"good" way), functions (methods) intended to work on them. [...]
So what you want is something along the lines of structs
with (private) data and functions that operate on the
data of the instance on which the function is invoked
(plus any other arguments, of course)? Is that all
or is there something more? Constructors? Destructors?
Copy assignment? Move assignment? References? I'm
trying to understand where you mean to draw the line.
(I assume throw/catch is meant to be on your list of 'not's
along with inheritance, etc.)
Ah. OK, I'll take ctors and dtors. And those imply something like
new and delete. Some of the others are nice-to-have, but not
critical, and wander more into the operator overloading area (copy
constructors, for example, although maybe having some way to _allow_
simple., C-style, struct assignment might be nice - and if you don't
allow that, you'll have to invoke object.yourcopymethod). Public and
private data items and methods, static as well. References have
limited usefulness without overloading. No exceptions, inheritance,
friendship, templates... If I want those, I know where C++ is.

That doubtless reflects some of my development practices, where I tend
to focus heavily on decomposing systems into (fairly opaque)
components with good interfaces.

A limited form of classes would help program structure by making
encapsulation much easier, as well as eliminating the vast majority of
namespace pollution.

Other people have come to different conclusions. Jacob Navia, for
example, thought so highly of operator overloading he wrote his own
compiler to support it. Personally I think operator overloading has
its niche, but it's a small one.
David Brown
2017-05-12 10:16:40 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by bartc
And it not only allows declarations anywhere (again by not enforcing a
boundary between them and statements), but they can be out-of-order. So
you could declare all your local variables at the end of a function if
you want!
A lot of programs have a usage pattern that, for accurate description, would
require more control over scope/lifetime than C supports. For example, in
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
double distance = sqrt(dx*dx+dy*dy);
double angle = atan2(dy,dx);
If code only needs to use dx and dy in the second line above, and nowhere
else, it would be helpful to be able to end their scope immediately after
it, but if scoping braces were used to end the scope of dx and dy they
would also end the scope of distance. Aside from the chicken-and-egg
problems of allowing programmers to use a new syntax without limiting the
range of tools they can use, perhaps it might be helpful to add an
"extern auto" qualifier which would cause an object declaration to take
{
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
extern auto double distance = sqrt(dx*dx+dy*dy);
extern auto double angle = atan2(dy,dx);
}
to create variables for use in the enclosing scope. An additional helpful
feature would be to say that an "extern auto" declaration without an
initialization would pass an already-declared block-local variable (which
might have been exported from an inner block) to the enclosing scope.
Most of the places where I've seen objects get declared mid-block would be
better accommodated by adding additional scoping blocks, if there were a
way to export variables from within them.
I have occasionally thought it would be nice to do something like that.
I much prefer to define and initialise my variables where possible, and
not to define them until I have something useful to put in them. With
your syntax, this sequence:

bool valid = false;
double result;
if (x >= 0) {
result = sqrt(x);
valid = true;
}
if (valid) printf("%f\n", result);

could become:

bool valid = false;
if (x >= 0) {
extern auto double result = sqrt(x);
valid = true;
}
if (valid) printf("%f\n", result);

Still, I think the use of something like this, the small advantage it
gives, would not come close to outweighing the confusion the concept
would cause, the conflicts with C++ syntax, and the ugly syntax.


If I were to change something here, it would be to allow a new
definition within the same local scope to end the previous scope:

int a = f();
int b = g(a);
int a = h(b);

The first "a" would end its scope when the new "a" begins, and can have
a different type or the same type.

You could perhaps also end a scope early by making a new identifier of
type "void":

int a = 1;
{
int a = 2;
void a;
int b = a; // Gets 1 from the outside "a"
}

One problem about this is if you have:

int a = f();
int a = g(&a);

Should the address passed refer to the old "a" which would would exist
up until the assignment, or should it refer to the new "a" which would
exist from the second "int a" declaration?
bartc
2017-05-12 10:49:54 UTC
Permalink
Raw Message
Post by David Brown
Post by s***@casperkitty.com
{
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
extern auto double distance = sqrt(dx*dx+dy*dy);
extern auto double angle = atan2(dy,dx);
}
bool valid = false;
double result;
if (x >= 0) {
result = sqrt(x);
valid = true;
}
if (valid) printf("%f\n", result);
bool valid = false;
if (x >= 0) {
extern auto double result = sqrt(x);
valid = true;
}
if (valid) printf("%f\n", result);
Still, I think the use of something like this, the small advantage it
gives,
There's no advantage (from the point of view of someone reading the
code). It replaces two straightforward lines with one complicated one.
And the scope rules seem obscure.
Post by David Brown
If I were to change something here, it would be to allow a new
int a = f();
int b = g(a);
int a = h(b);
The first "a" would end its scope when the new "a" begins, and can have
a different type or the same type.
That's great. So instead of only having two possible instances of a name
"A" within a block (not counting struct tag versions and labels), we can
now have an unlimited number!
Post by David Brown
You could perhaps also end a scope early by making a new identifier of
int a = 1;
{
int a = 2;
void a;
int b = a; // Gets 1 from the outside "a"
}
OK, now we're getting there. We need a way of defining a name whose
scope is unbounded by any } (until it gets to the end of the function),
and is terminated at any arbitrary place by an explicit command such as
this.

So:

int A; // A1
{
int A; // A2
{ new int A; // A3, unbounded by }
}
A; // A3
end A; // ends A3, A2 now in scope
A; // A2
}
A; // A1

It would be absolutely chaotic!

Why this obsession with these tiny scopes? They are plenty of languages
with weird and wonderful ideas - no variables, no assignments, no
statements - so why inflict them on C?

(BTW here's how the above would look in any code I would write:

int A; // A1
{
{
}
A; // A1
A; // A1
}
A; // A1

Which one would simpler to understand (regarding which A is which) and
would be understood by a wider range of people?)
--
bartc
David Brown
2017-05-12 13:21:37 UTC
Permalink
Raw Message
Post by bartc
Post by David Brown
Post by s***@casperkitty.com
{
double dx=(x2-x1), dy=(y2-x1); // Used *only* in next two lines
extern auto double distance = sqrt(dx*dx+dy*dy);
extern auto double angle = atan2(dy,dx);
}
bool valid = false;
double result;
if (x >= 0) {
result = sqrt(x);
valid = true;
}
if (valid) printf("%f\n", result);
bool valid = false;
if (x >= 0) {
extern auto double result = sqrt(x);
valid = true;
}
if (valid) printf("%f\n", result);
Still, I think the use of something like this, the small advantage it
gives,
There's no advantage (from the point of view of someone reading the
code). It replaces two straightforward lines with one complicated one.
And the scope rules seem obscure.
You mean there is no advantage from /your/ point of view, and the scope
rules are obscure to /you/. We already know you have trouble with block
scopes, both with understanding how they work and why they are useful.
Clearly something extra on top of that is going to be worse for you.

The advantage is that it replaces the two actions "define a variable"
and "assign a value to the variable" with one action "define a variable
with a given initialisation". It also keeps the scope to a reasonable
minimum. A great many programmers think this is a good thing - I
believe you are an exception here with your conviction that declaring
everything at the start of a function is better.

And you snipped the rest of my comment "would not come close to
outweighing the confusion the concept would cause". I also think it
would make the code less clear.
Post by bartc
Post by David Brown
If I were to change something here, it would be to allow a new
int a = f();
int b = g(a);
int a = h(b);
The first "a" would end its scope when the new "a" begins, and can have
a different type or the same type.
That's great. So instead of only having two possible instances of a name
"A" within a block (not counting struct tag versions and labels), we can
now have an unlimited number!
Yes. It is not hard, but there are a few tricks you need to learn.

1. Keep your functions of a sensible size.
2. Use sensible names.
3. Learn to understand the difference between extreme examples, and
real-world code.
Post by bartc
Post by David Brown
You could perhaps also end a scope early by making a new identifier of
int a = 1;
{
int a = 2;
void a;
int b = a; // Gets 1 from the outside "a"
}
OK, now we're getting there. We need a way of defining a name whose
scope is unbounded by any } (until it gets to the end of the function),
and is terminated at any arbitrary place by an explicit command such as
this.
No, we don't. You are misunderstanding what I wrote - I was /not/
proposing an alternative syntax for Supercat's idea.
Post by bartc
int A; // A1
{
int A; // A2
{ new int A; // A3, unbounded by }
}
A; // A3
end A; // ends A3, A2 now in scope
A; // A2
}
A; // A1
It would be absolutely chaotic!
I don't know what you mean here, because you have completely
misunderstood what I wrote, and then added your own new keywords "new"
and "end".
Post by bartc
Why this obsession with these tiny scopes?
The obsession is with clear and easily understood code. If a variable
has a small scope, it is easy to see where it starts, what it does, and
where it ends. Writing large functions with big collections of variable
definitions at the start means you are jumping all over the function to
see what it does, or while writing it. It is even worse when your
language allows you to put the definition later on, after the variable
has been in use (as your language does, AFAIUI).


Look, in C you can declare variables inside a block, and their scope
exists from that point until the end of the block. You understand that,
right?

int a = 1;
if (a == 1) {
int a; // New a
int b; // Local b
a = 2; // The new a
foo(a); // a == 2 here
b = 3;
bar(a, b); // a == 2, b == 3
}
foobar(a); // Back to the old a == 1


And in C99, you can mix declarations and statements. This means you can
write:

int a = 1;
if (a == 1) {
int a = 2; // New a
foo(a); // a == 2 here
int b = 3; // Local b
bar(a, b); // a == 2, b == 3
}
foobar(a); // Back to the old a == 1

This is equivalent to:

int a = 1;
if (a == 1) {
int a; // New a
a = 2; // The new a
foo(a); // a == 2 here
{
int b; // Local b
b = 3;
bar(a, b); // a == 2, b == 3
} // end of scope for b
} // end of scope for "new" a
foobar(a); // Back to the old a == 1

Are you still following?

What I am suggesting is the ability to write:

int a = 1;
if (a == 1) {
int a = 2; // New a
foo(a); // a == 2 here
int b = 3; // Local b
// The scope for the new a (a == 2) ends here
int a = 4; // Yet another new a
bar(a, b); // a == 4, b == 3
}
foobar(a); // Back to the old a == 1

This would be equivalent to:

int a = 1;
if (a == 1) {
int a; // New a
a = 2; // The new a
foo(a); // a == 2 here
{
int b; // Local b
b = 3;
{
int a; // Yet another new a
a = 4; // The YAN a
bar(a, b); // a == 4, b == 3
} // end of scope for YAN a
} // end of scope for b
} // end of scope for "new" a
foobar(a); // Back to the old a == 1


Is that clear enough?
Post by bartc
They are plenty of languages
with weird and wonderful ideas - no variables, no assignments, no
statements - so why inflict them on C?
There are indeed plenty of languages with weird and wonderful ideas. I
don't know of any language that has /this/ particular idea, but it might
exist somewhere.

And note that this is all about /additions/ to C - I can't see why you
think anyone is trying to /remove/ something from it. Yes, there are
languages without variables, assignments or statements (basically, you'd
be looking at a pure functional language), but they would be completely
different languages.
Post by bartc
int A; // A1
{
{
}
A; // A1
A; // A1
}
A; // A1
Which one would simpler to understand (regarding which A is which) and
would be understood by a wider range of people?)
It does not do the same thing, and is therefore irrelevant.

(But see also the point I made above about understanding the difference
between examples and real-world code.)
bartc
2017-05-12 14:14:06 UTC
Permalink
Raw Message
Post by David Brown
Post by bartc
Why this obsession with these tiny scopes?
The obsession is with clear and easily understood code. If a variable
has a small scope, it is easy to see where it starts, what it does, and
where it ends.
It would have to be an extremely small scope for that. With real uses of
such block scopes (eg. see the pastebin examples I posted recently), the
code is chaotic, and finding the boundaries of a variable's scope is
harder. Not helped by using the same name for two instances of the
variable within a function.

Whereas with my variables, you /know/ they have function scope. You
/know/ there is at most one of each. And if functions are kept small as
you yourself suggest, then that is not a problem.

Writing large functions with big collections of variable
Post by David Brown
definitions at the start means you are jumping all over the function to
see what it does, or while writing it. It is even worse when your
language allows you to put the definition later on, after the variable
has been in use (as your language does, AFAIUI).
That is invaluable when you are adding a function. You don't need to
worry about whether references to the function are before or after the
place where you're going to put it, or both, and whether a forward
declaration is needed.

Within functions, out-of-order declarations are unusual for normal code
(sometimes used for temporary or test code).
Post by David Brown
int a = 1;
if (a == 1) {
int a = 2; // New a
foo(a); // a == 2 here
int b = 3; // Local b
// The scope for the new a (a == 2) ends here
int a = 4; // Yet another new a
A dangerous feature I think. Currently it's an error to redeclare a name
twice within a block. You're proposing to do away with that check.

I assume that the second 'a' can have a different type from the first.
But is the a==2 version still accessible, within the scope of a==4,
through a pointer for example? (In your equivalent version below, it is.)

If not then I can't see the advantage of this over just writing 'a=4'
instead of 'int a=4'. Or is this part of some campaign where you are
only allowed to assign to a variable once, or can only initialise it at
declaration (effectively doing away with assignment)?
Post by David Brown
bar(a, b); // a == 4, b == 3
}
foobar(a); // Back to the old a == 1
int a = 1;
if (a == 1) {
int a; // New a
a = 2; // The new a
foo(a); // a == 2 here
{
int b; // Local b
b = 3;
{
int a; // Yet another new a
a = 4; // The YAN a
bar(a, b); // a == 4, b == 3
} // end of scope for YAN a
} // end of scope for b
} // end of scope for "new" a
foobar(a); // Back to the old a == 1
Is that clear enough?
I can see it. But I'm struggling to see the benefit.

I can appreciate the advantages of more controlled scope on a larger
scale. If modules A and B want to share functions and variables, for
example, then those names will be accessible to C, D and E as well.

With some languages (a couple of mine for example), those names can be
kept private between A and B or least they will not clash with anything
exported by C or D.

But with your in-function examples, especially in real code with longer
names and more elaborate expressions, you're always going to be trying
to see what name is what.
--
bartc
David Brown
2017-05-12 15:04:42 UTC
Permalink
Raw Message
Post by bartc
Post by David Brown
Post by bartc
Why this obsession with these tiny scopes?
The obsession is with clear and easily understood code. If a variable
has a small scope, it is easy to see where it starts, what it does, and
where it ends.
It would have to be an extremely small scope for that. With real uses of
such block scopes (eg. see the pastebin examples I posted recently), the
code is chaotic, and finding the boundaries of a variable's scope is
harder. Not helped by using the same name for two instances of the
variable within a function.
The code you showed is an absolute mess. It may have come from a
popular open source project, but it is still a total disaster for
readability and maintainability. The second link, with smaller scopes
for variables, is marginally less bad - but it too has massive numbers
of variables declared in all the wrong places.

The standard since the dawn of time has been that if a function is too
big to fit comfortably in a screen on your editor, then it is probably
too big.

Now, in some code long functions can make sense. Typically that would
be a function where you simply have a long list of things to do, and the
use of parameters and/or some common local variables means it is easier
to have the bits sequentially in one function rather than splitting it
up and passing lots of data between the sub-functions. In such cases,
local variables with small block scopes is a massive win for readability.

And for more normal-sized functions, well, small block scopes are also a
massive win for readability.
Post by bartc
Whereas with my variables, you /know/ they have function scope.
(To save others the effort - only labels can have "function scope" in C.
You mean they have block scope in the outer block of the function.)
Post by bartc
You
/know/ there is at most one of each. And if functions are kept small as
you yourself suggest, then that is not a problem.
Yes, and you /know/ their definitions are separate from their uses so
that you don't know how they will be used when you define them, and you
don't know how their are defined when you use them. You /know/ you have
to jump back and forth in your editor when trying to find them or add
new variables, rather than seeing them a line or two away from where you
are. You /know/ that you are going to see a variable with a meaningless
name like "temp" used repeatedly for different purposes. You /know/
there are going to be left-overs as code changes, where the use of a
variable has been removed but its declaration is still there.

You know lots of things when you write functions that way.
Post by bartc
Writing large functions with big collections of variable
Post by David Brown
definitions at the start means you are jumping all over the function to
see what it does, or while writing it. It is even worse when your
language allows you to put the definition later on, after the variable
has been in use (as your language does, AFAIUI).
That is invaluable when you are adding a function. You don't need to
worry about whether references to the function are before or after the
place where you're going to put it, or both, and whether a forward
declaration is needed.
I don't worry - I just define my functions before I use them. Some
people prefer to declare their functions so that they can define them in
different orders - that works too, and I don't imagine they worry too
much either.

That said, I would not object to C being able to accept function
definitions within a translation unit in any order, without having
forward declarations. It would be fine for structs and unions too. But
allowing variables to be used before defining or declaring them is
asking for trouble, IMHO.
Post by bartc
Within functions, out-of-order declarations are unusual for normal code
(sometimes used for temporary or test code).
Post by David Brown
int a = 1;
if (a == 1) {
int a = 2; // New a
foo(a); // a == 2 here
int b = 3; // Local b
// The scope for the new a (a == 2) ends here
int a = 4; // Yet another new a
A dangerous feature I think. Currently it's an error to redeclare a name
twice within a block. You're proposing to do away with that check.
Yes, it is a new feature that I am proposing. It is not "doing away
with a check" - it is a new feature. Making a new definition with the
same name as an existing identifier is not doing away with a check, but
specifically ending the scope of the old identifier in this case. (That
makes it a little different from the translation into extra blocks.)

There are details to work out and specify in how this works - it could
be an issue if a reference to a variable is taken earlier on and that
variable is then replaced by a new one of the same name. Should the
lifetime of the old one carry on to the end of the block, or should it
stop at the declaration of the new one?
Post by bartc
I assume that the second 'a' can have a different type from the first.
Yes. (An alternative proposal would be to simply make the second
declaration redundant, and not introduce a new variable, but obviously
the type would have to be the same.)
Post by bartc
But is the a==2 version still accessible, within the scope of a==4,
through a pointer for example? (In your equivalent version below, it is.)
In the conversion below, it is still alive even though its scope is
hidden. I am in two minds about whether or not it should be that way,
or whether it should "die" when the new one takes effect. For C, there
is little disadvantage in letting it remain alive - if you don't access
it via a pointer, the compiler can see that it is dead and re-use the
space. For C++, it is a bit different - there is the question of when
the destructor is run. So this is a question that would have to be
considered and defined carefully.
Post by bartc
If not then I can't see the advantage of this over just writing 'a=4'
instead of 'int a=4'. Or is this part of some campaign where you are
only allowed to assign to a variable once, or can only initialise it at
declaration (effectively doing away with assignment)?
Different types would be allowed. Redefinition with the same type would
be mostly for convenience when moving code sections around or copying them.
Post by bartc
Post by David Brown
bar(a, b); // a == 4, b == 3
}
foobar(a); // Back to the old a == 1
int a = 1;
if (a == 1) {
int a; // New a
a = 2; // The new a
foo(a); // a == 2 here
{
int b; // Local b
b = 3;
{
int a; // Yet another new a
a = 4; // The YAN a
bar(a, b); // a == 4, b == 3
} // end of scope for YAN a
} // end of scope for b
} // end of scope for "new" a
foobar(a); // Back to the old a == 1
Is that clear enough?
I can see it. But I'm struggling to see the benefit.
I can appreciate the advantages of more controlled scope on a larger
scale. If modules A and B want to share functions and variables, for
example, then those names will be accessible to C, D and E as well.
That is a different matter entirely - and I agree that it would be nice
to have a solution to that. Namespaces (from C++) go some way to
solving that problem, and I see no reason why C could not copy that
feature from C++.
Post by bartc
With some languages (a couple of mine for example), those names can be
kept private between A and B or least they will not clash with anything
exported by C or D.
But with your in-function examples, especially in real code with longer
names and more elaborate expressions, you're always going to be trying
to see what name is what.
No, you would not.

If you actually tried working in a "small variable scope" manner, I
believe you would see its advantages. My proposal here just makes it a
little nicer.
s***@casperkitty.com
2017-05-12 15:27:52 UTC
Permalink
Raw Message
Post by bartc
Post by David Brown
If I were to change something here, it would be to allow a new
int a = f();
int b = g(a);
int a = h(b);
The first "a" would end its scope when the new "a" begins, and can have
a different type or the same type.
That's great. So instead of only having two possible instances of a name
"A" within a block (not counting struct tag versions and labels), we can
now have an unlimited number!
C presently limits the number of bindings a symbol can have within a block
to two, but allows a symbol to be associated at any point in the code with
with an arbitrary number of live objects within the current function
invocation context, even though only one is accessible.

Consider the code:

volatile int zzq;
void test(void)
{
int a=42;
int i=2;
do
{
zzq = a;
...
a=123456789;
zzq = a;
}
while(--i);
zzq = a;
}

If the code in the "..." is guaranteed not to prevent the "do" loop from
executing twice in normal fashion [i.e. it doesn't alter "i", nor "break",
nor anything like that] and doesn't write to zzq, what sequences of writes
to zzq might occur? Can you see how the sequence might be, e.g. {42,
123456792, 42, 123456792, 42}?

Having a guarantee that something like:

...
zzq = a;
} while(--i);
zzq = a;

could only be legal in cases where both "a" have the same meaning would seem
more helpful than having a guarantee that something like:

zzq = a;
...
zzq = a;
...
zzq = a;

would only be legal if at least two of the three uses of "a" have the same
meaning.
Thiago Adams
2017-05-11 12:03:16 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.
I don't want to have to use tools just to understand code. (Otherwise
what's the point of a language having syntax? Just use some internal
format for source code, and rely on a tool for rendering in a syntax and
style of your choice.)
Post by Ben Bacarisse
It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
Smaller scope tend to reduce the use of either indeterminate objects
or objects initialised with meaningless "place-holder" values.
What happened to all the people telling us to keep functions to ten
lines or less? Then having multiple scopes within such a span would be
ludicrous.
Post by Ben Bacarisse
They localise changes. If I alter the upper bound (or otherwise alter
the exit) of
for (int i = lo; i < f(lo); i++) result = g(i, result);
I know I can't be messing with any code that has assumed that i == f(lo)
below the loop.
That's probably the only example where a localised loop index name can
make sense. In fact, here such a local index name is desirable, so you
don't even want to bother declaring it. [Not practical in C as there is
no official concept of a loop index variable]
How about const variables?
const int size = pStruct->Size;

Can this const be a tip for the
optimizer, or, in other words, can this style produce better code?

In my code, I use small scopes for variables,
and I initialize everything on declaration.
I try to create initialization that don't fail using
initializes. Sometimes I create a "empty" state for that.
But when I need a initialized state that can fail then I have
an unitized var.

Var var1;
if (Init(&var1)) { }


When I see:

int a;
int c;
int b;

a = ..;
b = ..;
c = a + b;

I do:

int a = ...;
int b = ... ;
int c = a + b;
bartc
2017-05-11 13:29:28 UTC
Permalink
Raw Message
Post by Thiago Adams
In my code, I use small scopes for variables,
and I initialize everything on declaration.
I try to create initialization that don't fail using
initializes. Sometimes I create a "empty" state for that.
But when I need a initialized state that can fail then I have
an unitized var.
Var var1;
if (Init(&var1)) { }
int a;
int c;
int b;
a = ..;
b = ..;
c = a + b;
int a = ...;
int b = ... ;
int c = a + b;
Well, it would be this:

<otherdecls>
int a,b,c;

<othercode>

a=X;
b=Y;
c=a+b;

The trouble is after changing it to:

<otherdecls>

<othercode>

int a=X;
int b=Y;
int c=a+b;

You then find you need to do something with a earlier on:

<otherdecls>

a=Z;
...

<othercode>

int a=X;
int b=Y;
int c=a+b;

Now a's declaration is in the wrong place! Worse, there might be another
a - of the wrong type - in an outer scope, and it will resolve to that.
Not a compile error, but it might work wrongly.

Also, you may decide that this last block needs to be conditional:

if (cond) {
int a=X;
int b=Y;
int c=a+b;
}

(or maybe there's an else part with an alternative initialiser, or maybe
sometimes a is defined in terms of b, and other times b is defined in
terms of a.)

Now you can't do this later:

if (cond) d=a-b;

as a and b are out of scope.

I can give dozens of examples; it just seems to me that these
tight-binding declarations are a strait-jacket. And in real code, things
will be considerably more muddled, with long, easy-to-confuse names, and
multiple instances of a, b and c.
--
bartc
Ian Collins
2017-05-12 08:04:54 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by bartc
Post by Ben Bacarisse
They localise changes. If I alter the upper bound (or otherwise alter
the exit) of
for (int i = lo; i < f(lo); i++) result = g(i, result);
I know I can't be messing with any code that has assumed that i == f(lo)
below the loop.
That's probably the only example where a localised loop index name can
make sense. In fact, here such a local index name is desirable, so you
don't even want to bother declaring it. [Not practical in C as there is
no official concept of a loop index variable]
How about const variables?
const int size = pStruct->Size;
Can this const be a tip for the
optimizer, or, in other words, can this style produce better code?
Even if they don't, const variables are a compelling argument in favour
of declarations at the point of first use.
--
Ian
Tim Rentsch
2017-05-14 20:27:13 UTC
Permalink
Raw Message
Post by Ian Collins
Post by Thiago Adams
Post by bartc
Post by Ben Bacarisse
They localise changes. If I alter the upper bound (or otherwise alter
the exit) of
for (int i = lo; i < f(lo); i++) result = g(i, result);
I know I can't be messing with any code that has assumed that i == f(lo)
below the loop.
That's probably the only example where a localised loop index name can
make sense. In fact, here such a local index name is desirable, so you
don't even want to bother declaring it. [Not practical in C as there is
no official concept of a loop index variable]
How about const variables?
const int size = pStruct->Size;
Can this const be a tip for the
optimizer, or, in other words, can this style produce better code?
Even if they don't, const variables are a compelling argument in
favour of declarations at the point of first use.
Being able to use const does provide one motivation to place a
declaration at the point of first use. Some people find that
ability important enough to argue that it should be done whenever
possible; others consider other factors equally or sometimes
more important, and draw different conclusions.
Patrick.Schluter
2017-05-11 19:56:31 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.
It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that

- the code always gets shorter (1 line of declaration +1 line first
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
- for loop declared variables allows to copy paste code more easily.
- refactoring long functions in to several smaller ones becomes order of
magnitude easier if you declare the variable where it is used. I was
surprized to see how often a variable was declared at the beginning and
only used twice at the end of the function in a very unlikely error path.

The funny thing is that doing that has brought the need for the if( with
declaration as the pattern of

type var = call();
if(var == somethin) callsomething(var);

is really very frequent.
Ben Bacarisse
2017-05-11 22:27:04 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't
clutter up
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
the rest of the code. That way I have smaller regions of code to
verify.
Post by Ben Bacarisse
Post by bartc
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.
It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
I'm currently in the process of replacing systematically on our
porject the style of declaration, from the standard C way to the new
C99 in-code declarations. What I have notices during that process is
that
- the code always gets shorter (1 line of declaration +1 line first
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
- for loop declared variables allows to copy paste code more easily.
- refactoring long functions in to several smaller ones becomes order
of magnitude easier if you declare the variable where it is used. I
was surprized to see how often a variable was declared at the
beginning and only used twice at the end of the function in a very
unlikely error path.
Interesting observations. Thanks.

I'm curious to know how you rate the original code quality and to know
what sort of average function size it has. The potential benefits might
depend to some extent on these.
Post by bartc
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
course:

(var => if (var == something) callsomething(var))(call());

and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
--
Ben.
bartc
2017-05-11 23:26:10 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our
porject the style of declaration, from the standard C way to the new
C99 in-code declarations. What I have notices during that process is
that
(I suspect any sort of systematic review will reduce the code size as
redundant parts of discovered. Maybe turning in-place declarations to
clustered ones will have done the same!)
Post by Ben Bacarisse
Post by Patrick.Schluter
- the code always gets shorter (1 line of declaration +1 line first
(Always?

int a,b,c; plus 3 lines of initialisation, would turn into

int a = ...
int b = ...
int c = ....

Four lines into three, rather than six lines into three. But these are
longer lines as the type is now duplicated.)
Post by Ben Bacarisse
Post by Patrick.Schluter
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
(And you haven't yet found the ones that have been introduced!)
Post by Ben Bacarisse
Post by Patrick.Schluter
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
(var => if (var == something) callsomething(var))(call());
and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
You want a special variable such "_" or "$":

if ($ == something) callsomething($);

This can either be language supported (so is always available and always
assumes the type of the last assignment to it), or can be declared once
in a function then used as necessary (but each $ can only be of one type).

In this example, you are not really interested in 'var' other than as a
mechanism to carry over a temporary value to the expression, nor in the
type it needs to be.

So you don't particularly want a new feature just to declare a variable
that you don't really want either.
--
bartc
Ben Bacarisse
2017-05-12 00:16:14 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our
porject the style of declaration, from the standard C way to the new
C99 in-code declarations. What I have notices during that process is
that
(I suspect any sort of systematic review will reduce the code size as redundant parts of discovered. Maybe turning in-place declarations to clustered ones will have done the same!)
Post by Ben Bacarisse
Post by Patrick.Schluter
- the code always gets shorter (1 line of declaration +1 line first
(Always?
int a,b,c; plus 3 lines of initialisation, would turn into
int a = ...
int b = ...
int c = ....
Four lines into three, rather than six lines into three. But these are longer lines as the type is now duplicated.)
Post by Ben Bacarisse
Post by Patrick.Schluter
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
(And you haven't yet found the ones that have been introduced!)
Post by Ben Bacarisse
Post by Patrick.Schluter
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
(var => if (var == something) callsomething(var))(call());
and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
No I don't. By all means tell me what *you* want -- it's seeing such
diverse options that makes Usenet interesting -- but I don't see how you
can possibly know what I want.
if ($ == something) call something($);
This can either be language supported (so is always available and
always assumes the type of the last assignment to it), or can be
declared once in a function then used as necessary (but each $ can
only be of one type).
I can think of at least three ways in which that hack offers less than I
what I want from a properly declared and scoped name in C.
In this example, you are not really interested in 'var' other than as
a mechanism to carry over a temporary value to the expression, nor in
the type it needs to be.
It's not my example. Patrick obviously chose deliberately generic
names. There are situations where I *am* interested in the name and/or
the type. And I am always interested in the scope.

<snip>
--
Ben.
bartc
2017-05-12 00:35:33 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by Ben Bacarisse
Post by Patrick.Schluter
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
(var => if (var == something) callsomething(var))(call());
and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
No I don't. By all means tell me what *you* want -- it's seeing such
diverse options that makes Usenet interesting -- but I don't see how you
can possibly know what I want.
I put forward my proposal because I couldn't figure out yours. (Where do
you start? These things need to be obvious.)
Post by Ben Bacarisse
if ($ == something) call something($);
(Result of call() should be assigned to $ first.)
Post by Ben Bacarisse
I can think of at least three ways in which that hack offers less than I
what I want from a properly declared and scoped name in C.
In this example, you are not really interested in 'var' other than as
a mechanism to carry over a temporary value to the expression, nor in
the type it needs to be.
It's not my example. Patrick obviously chose deliberately generic
names. There are situations where I *am* interested in the name and/or
the type. And I am always interested in the scope.
No, this pattern is only about taking the result of one call and passing
it to another. If it wasn't for the conditional, it would simply be
written as:

callsomething(call())

No intermediate variable to be defined.
--
bartc
Ben Bacarisse
2017-05-12 00:58:04 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by Ben Bacarisse
Post by Patrick.Schluter
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
(var => if (var == something) callsomething(var))(call());
and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
No I don't. By all means tell me what *you* want -- it's seeing such
diverse options that makes Usenet interesting -- but I don't see how you
can possibly know what I want.
I put forward my proposal because I couldn't figure out yours. (Where
do you start? These things need to be obvious.)
You could always ask, I suppose. Anyway, I have no proposal. I was
showing how parameter binding in other languages achieves the desired
effect.
Post by bartc
Post by Ben Bacarisse
if ($ == something) call something($);
(Result of call() should be assigned to $ first.)
Post by Ben Bacarisse
I can think of at least three ways in which that hack offers less than I
what I want from a properly declared and scoped name in C.
In this example, you are not really interested in 'var' other than as
a mechanism to carry over a temporary value to the expression, nor in
the type it needs to be.
It's not my example. Patrick obviously chose deliberately generic
names. There are situations where I *am* interested in the name and/or
the type. And I am always interested in the scope.
No,
What are you saying "no" to? You don't think there are situations where
I am interesting the name (so $ or _ would be poor choices)? Or you
don't think there are situations where I care about the type and simply
assigning $ or _ might not produce the desired result? Or maybe you
don't think I really do care about the scope which is why one universal
$ or _ is less than ideal?
Post by bartc
this pattern is only about taking the result of one call and
passing it to another.
Clearly it isn't.
Post by bartc
If it wasn't for the conditional, it would
callsomething(call())
No intermediate variable to be defined.
No I'm lost. In a discussion of scopes, what would be the point of an
example that did not have a named variable? There would have been
nothing to say if it weren't for the conditional.
--
Ben.
Patrick.Schluter
2017-05-12 20:36:23 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by Ben Bacarisse
Post by Patrick.Schluter
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
(var => if (var == something) callsomething(var))(call());
and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
No I don't. By all means tell me what *you* want -- it's seeing such
diverse options that makes Usenet interesting -- but I don't see how you
can possibly know what I want.
if ($ == something) call something($);
This can either be language supported (so is always available and
always assumes the type of the last assignment to it), or can be
declared once in a function then used as necessary (but each $ can
only be of one type).
I can think of at least three ways in which that hack offers less than I
what I want from a properly declared and scoped name in C.
In this example, you are not really interested in 'var' other than as
a mechanism to carry over a temporary value to the expression, nor in
the type it needs to be.
It's not my example. Patrick obviously chose deliberately generic
names. There are situations where I *am* interested in the name and/or
the type. And I am always interested in the scope.
Indeed, I used generic names. Maybe if I had used the usual foo, bar and
foobar (or for the French toto, titi, tata) it would have been more obvious.
But to come back to what I meant. The pattern that came quit frequently
was the need to have a temporary variable holding the result of a call
because the value returned appears more than once in the if/else clause.
With pure function one can sometime get away with the repetition but
very often it is not possible. Here an example of what I mean.
int var = getc();
if(var == 'A') { ...use var... }
var not used anymore after that.

That pattern was not rare and several times I would have found it handy
to have something similar to the for(decls.... The same happens with
while(.) loops, but there it can sometimes be changed by using a for(
loop. Funnily, for do{}while() loop though, it's generally not that
useful as you can not use a variable declared inside the statement in
the condition as it is out of scope.

Just my observation after a few months of using that feature.
Patrick.Schluter
2017-05-12 20:19:47 UTC
Permalink
Raw Message
Post by bartc
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our
porject the style of declaration, from the standard C way to the new
C99 in-code declarations. What I have notices during that process is
that
(I suspect any sort of systematic review will reduce the code size as
redundant parts of discovered. Maybe turning in-place declarations to
clustered ones will have done the same!)
As I said in the answer to Ben Bacarisse, it's partially true but a good
part comes from the declaration close to where it's used. At the
beginning I was myself very sceptic of the benefits (I used to criticize
C++ for that) but the more I did it the more I saw the advantages. Of
course, one has to be careful as it is possible to introduce new bugs
but in general, my experience has been very positive.
Post by bartc
Post by Patrick.Schluter
- the code always gets shorter (1 line of declaration +1 line first
(Always?
int a,b,c; plus 3 lines of initialisation, would turn into
int a = ...
int b = ...
int c = ....
int a=..., b=..., c=...;

but granted, always is a bit exagerated.
Post by bartc
Four lines into three, rather than six lines into three. But these are
longer lines as the type is now duplicated.)
Post by Patrick.Schluter
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
(And you haven't yet found the ones that have been introduced!)
Patrick.Schluter
2017-05-12 20:06:18 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't
clutter up
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
the rest of the code. That way I have smaller regions of code to
verify.
Post by Ben Bacarisse
Post by bartc
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it
might have been declared somewhere in between.
When you just put all the declarations at the top of a function you have
to check every line for occurrences of every variable (if you are doing
any sort of semi-formal reasoning about your code), but both this and
your remark, whist being genuine problems with each approach, are
largely trivial in that there are simple tools to help in both cases.
It's hard to put into words why I find it so very much more comfortable
to do it my way. I suspect a lot of it comes down to the fact that we
think about code in very different ways, but here are a few thoughts
I'm currently in the process of replacing systematically on our
porject the style of declaration, from the standard C way to the new
C99 in-code declarations. What I have notices during that process is
that
- the code always gets shorter (1 line of declaration +1 line first
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
- for loop declared variables allows to copy paste code more easily.
- refactoring long functions in to several smaller ones becomes order
of magnitude easier if you declare the variable where it is used. I
was surprized to see how often a variable was declared at the
beginning and only used twice at the end of the function in a very
unlikely error path.
Interesting observations. Thanks.
I'm curious to know how you rate the original code quality and to know
what sort of average function size it has. The potential benefits might
depend to some extent on these.
The original code was not really good to begin with. The initial
developpers had the tendency to write really big convoluted functions
which did several unrelated things. A part of the code enhancement comes
from the moving of the declarations but granted, some of it comes only
because doing that refactoring make me read the code more thoroughly.
Similarly, documenting with doxygen also often trigger rewrites because
trying to understand the parameters to explain them uncovers better ways
to organise code.
So, the gain comes partially from the moving of declaration but often
only because of simple review.
Post by Ben Bacarisse
Post by bartc
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
Languages with anonymous functions get that (with scoping) for free of
(var => if (var == something) callsomething(var))(call());
and many others have some form of 'let' or 'with' or 'where' to
introduce local bindings. Often these are just syntactic sugar for a
function call.
GOTHIER Nathan
2017-05-12 00:09:28 UTC
Permalink
Raw Message
On Thu, 11 May 2017 21:56:31 +0200
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that
Please define what's standard C for you since C99 is standard... Once more,
could you provide some snippets to be more explicit about your concept.
Patrick.Schluter
2017-05-12 20:38:14 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 11 May 2017 21:56:31 +0200
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that
Please define what's standard C for you since C99 is standard... Once more,
could you provide some snippets to be more explicit about your concept.
the old K&R and C89 way. Wasn't it obvious from the context?
James R. Kuyper
2017-05-12 21:15:56 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by GOTHIER Nathan
On Thu, 11 May 2017 21:56:31 +0200
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that
Please define what's standard C for you since C99 is standard... Once more,
could you provide some snippets to be more explicit about your concept.
the old K&R and C89 way. Wasn't it obvious from the context?
No, it isn't. In context, I'd obviously expect "standard C" to refer to
C2011, which has been the current C standard for six years now. This is
clearly in conflict with your use of the term "new" in the above
message, which is what leads to questions about what you actually meant
by the term.
s***@casperkitty.com
2017-05-12 22:10:43 UTC
Permalink
Raw Message
Post by James R. Kuyper
No, it isn't. In context, I'd obviously expect "standard C" to refer to
C2011, which has been the current C standard for six years now. This is
clearly in conflict with your use of the term "new" in the above
message, which is what leads to questions about what you actually meant
by the term.
The phrase "Standard C" should be stricken from the lexicon unless or until
the Committee decides via some means to ensure that every program whose
meaning is defined by some version of the Standard will have that same
meaning defined by all future versions of the Standard. Many standards
are able to accomplish such a thing via use of version headers in files.
If an HTML file starts with a header that identifies it as conforming to a
particular version of the HTML standard, the meaning of any directives
within it will not change even if later standards define those directives
differently. Unfortunately, C99 fails to define the behavior of some source
texts whose behavior was unambiguously defined in C89, and fails to provide
any reasonable means by which those source texts could be adapted to have
defined behavior in all the cases where they had previously.
Robert Wessel
2017-05-13 05:02:43 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by James R. Kuyper
No, it isn't. In context, I'd obviously expect "standard C" to refer to
C2011, which has been the current C standard for six years now. This is
clearly in conflict with your use of the term "new" in the above
message, which is what leads to questions about what you actually meant
by the term.
The phrase "Standard C" should be stricken from the lexicon unless or until
the Committee decides via some means to ensure that every program whose
meaning is defined by some version of the Standard will have that same
meaning defined by all future versions of the Standard. Many standards
are able to accomplish such a thing via use of version headers in files.
If an HTML file starts with a header that identifies it as conforming to a
particular version of the HTML standard, the meaning of any directives
within it will not change even if later standards define those directives
differently. Unfortunately, C99 fails to define the behavior of some source
texts whose behavior was unambiguously defined in C89, and fails to provide
any reasonable means by which those source texts could be adapted to have
defined behavior in all the cases where they had previously.
That would preclude things even as simple as the addition of new
keywords to the language. Nor does the history of language standards
does not offer evidence that such an approach is realistic. IOW,
you're arguing for complete stagnation. Which actually appears to be
what you want, weren't you the one arguing that the C74 documentation
expresses the "real" ideals of C? (If that wasn't you, I apologize).

I'm reminded of the post Cobol-74 (eventually '85) committee that was
so tied by users refusing to accept even minor incompatibilities (at
one point Traveler's Insurance was threatening to sue the committee
because of the conversion cost they thought they were going to incur),
that it took them the better part of a decade to get the standard
knocked out.

In any event, the usual approach is for compiler vendors to offer both
a "old" and "new" mode of operation. That seems to work well enough.
Tim Rentsch
2017-05-13 16:11:52 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Thu, 11 May 2017 21:56:31 +0200
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that
Please define what's standard C for you since C99 is standard... Once more,
could you provide some snippets to be more explicit about your concept.
the old K&R and C89 way. Wasn't it obvious from the context?
No, it isn't. [...]
In my view the meaning was readily apparent to anyone
who took a moment to think about it (and was generally
familiar with C89/C90 and C99, and their differences).
But then I'm used to looking at things from different
angles to find out if someone might have phrased their
meaning in ways I didn't expect.
GOTHIER Nathan
2017-05-12 22:59:44 UTC
Permalink
Raw Message
On Fri, 12 May 2017 22:38:14 +0200
Post by Patrick.Schluter
the old K&R and C89 way. Wasn't it obvious from the context?
I assumed C89 from the context only because that's the first burocratic and the
most commonly supported definition by compilers. However C has many definitions
and your sentence is ambiguous assuming C99 isn't formally defined by the ISO
committee.
Robert Wessel
2017-05-13 05:04:11 UTC
Permalink
Raw Message
On Sat, 13 May 2017 00:59:44 +0200, GOTHIER Nathan
Post by GOTHIER Nathan
On Fri, 12 May 2017 22:38:14 +0200
Post by Patrick.Schluter
the old K&R and C89 way. Wasn't it obvious from the context?
I assumed C89 from the context only because that's the first burocratic and the
most commonly supported definition by compilers. However C has many definitions
and your sentence is ambiguous assuming C99 isn't formally defined by the ISO
committee.
C99 was defined in standard ISO/IEC 9899:1999.
GOTHIER Nathan
2017-05-13 11:17:05 UTC
Permalink
Raw Message
On Sat, 13 May 2017 00:04:11 -0500
Post by Robert Wessel
C99 was defined in standard ISO/IEC 9899:1999.
Please tell me more...
j***@verizon.net
2017-05-13 13:37:56 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Sat, 13 May 2017 00:04:11 -0500
Post by Robert Wessel
C99 was defined in standard ISO/IEC 9899:1999.
Please tell me more...
<www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>

You wrote earlier:
"... assuming C99 isn't formally defined by the ISO committee."

I'm curious - what misconception led you to make such a bizarre assumption? As you'll see when you read that document, C99 has been very formally defined, and it was indeed the ISO committee which did the defining.
Stefan Ram
2017-05-13 14:16:12 UTC
Permalink
Raw Message
Post by j***@verizon.net
I'm curious - what misconception led you to make such a
bizarre assumption? As you'll see when you read that
document, C99 has been very formally defined, and it was
indeed the ISO committee which did the defining.
Only the syntax is specified formally by BNF. (But that BNF
might contain informal parts, and some say that there are
some problems due to the possibility of typedefs.)

But the semantics are given in English. This is not what one
calls »a formal semantic specification« in computer science.

But check out,

A FORMAL SEMANTICS OF C WITH APPLICATIONS

BY
CHARLES MCEWEN ELLISON III
DISSERTATION

Submitted in partial fulfillment of the requirements for
the degree of Doctor of Philosophy in Computer Science
in the Graduate College of the University of Illinois at
Urbana-Champaign, 2012

Urbana, Illinois

(end of citation)

and

Technical Report UCAM-CL-TR-453
ISSN 1476-2986
Number 453
UNIVERSITY OF CAMBRIDGE
Computer Laboratory

C formalised in HOL

Michael Norrish

December 1998

JJ Thomson Avenue
Cambridge CB3 0FD
United Kingdom
www.cl.cam.ac.uk/

(end of citation).
James Kuyper
2017-05-13 14:29:08 UTC
Permalink
Raw Message
Post by Stefan Ram
Post by j***@verizon.net
I'm curious - what misconception led you to make such a
bizarre assumption? As you'll see when you read that
document, C99 has been very formally defined, and it was
indeed the ISO committee which did the defining.
Only the syntax is specified formally by BNF. (But that BNF
might contain informal parts, and some say that there are
some problems due to the possibility of typedefs.)
But the semantics are given in English. This is not what one
calls �a formal semantic specification� in computer science.
Well, my major was Physics, not CS, so that's not the concept that comes
to mind when I think "formal definition". Note that Nathan used neither
"semantic" nor "specification", so at least two thirds of your term is
more specific than his comment was.

The standard uses a very specialized subset of English, with precisely
defined jargon that has meanings different from those that apply to
ordinary English usage (in some cases, they even differ from the
ordinary meanings that apply when using English to discuss computer
programming in general). Within the limitations of English, it provides
a pretty formal definition of C.
Stefan Ram
2017-05-13 14:46:37 UTC
Permalink
Raw Message
Post by James Kuyper
Post by Stefan Ram
Post by j***@verizon.net
I'm curious - what misconception led you to make such a
bizarre assumption? As you'll see when you read that
document, C99 has been very formally defined, and it was
indeed the ISO committee which did the defining.
Only the syntax is specified formally by BNF. (But that BNF
might contain informal parts, and some say that there are
some problems due to the possibility of typedefs.)
But the semantics are given in English. This is not what one
calls »a formal semantic specification« in computer science.
Well, my major was Physics, not CS,
FWIW, my "major" was Physics, too (the "minor" being Maths).
(The correct German designation says that I am a
"Diplom-Physiker" [with a "Nebenfach Mathematik"]). So, I,
too, am only self-educated when it comes to computer science.

For a common meaning of »formal specification«, readers
might take a look at

en.wikipedia.org/wiki/Formal_specification

.
GOTHIER Nathan
2017-05-13 16:14:37 UTC
Permalink
Raw Message
On Sat, 13 May 2017 06:37:56 -0700 (PDT)
Post by j***@verizon.net
I'm curious - what misconception led you to make such a bizarre assumption? As
you'll see when you read that document, C99 has been very formally defined, and
it was indeed the ISO committee which did the defining.
It's not a misconception but the logic extracted from the sentence pretending
there is a standard C and C99... which would not be standard by dissociation.

Actually the true misconception, is your trial to put an idea I haven't
sustained on my back though I only commented it from the OP.
Keith Thompson
2017-05-13 21:04:12 UTC
Permalink
Raw Message
Post by Robert Wessel
On Sat, 13 May 2017 00:59:44 +0200, GOTHIER Nathan
Post by GOTHIER Nathan
On Fri, 12 May 2017 22:38:14 +0200
Post by Patrick.Schluter
the old K&R and C89 way. Wasn't it obvious from the context?
I assumed C89 from the context only because that's the first
burocratic and the most commonly supported definition by
compilers. However C has many definitions and your sentence is
ambiguous assuming C99 isn't formally defined by the ISO committee.
C99 was defined in standard ISO/IEC 9899:1999.
And ISO/IEC 9899:2011 (E) says

This third edition cancels and replaces the second edition, ISO/IEC
9899:1999, which has been technically revised

C99 *was* formally defined by ISO, but strictly speaking it no longer
is.

(The terms "C89", "C90", "C99", and "C11" are informal names, not
formally defined by any standard document as far as I know; I don't
know whether that's what the previous poster was referring to.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
GOTHIER Nathan
2017-05-13 21:44:07 UTC
Permalink
Raw Message
On Sat, 13 May 2017 14:04:12 -0700
Post by Keith Thompson
And ISO/IEC 9899:2011 (E) says
This third edition cancels and replaces the second edition, ISO/IEC
9899:1999, which has been technically revised
C99 *was* formally defined by ISO, but strictly speaking it no longer
is.
I haven't found any C99 reference in ISO 9899 documents except from a rationale
which isn't the standard formal definition.
Post by Keith Thompson
(The terms "C89", "C90", "C99", and "C11" are informal names, not
formally defined by any standard document as far as I know; I don't
know whether that's what the previous poster was referring to.)
In fact you've gone too far in the details and that wasn't my point.
j***@verizon.net
2017-05-14 01:22:57 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Sat, 13 May 2017 14:04:12 -0700
Post by Keith Thompson
And ISO/IEC 9899:2011 (E) says
This third edition cancels and replaces the second edition, ISO/IEC
9899:1999, which has been technically revised
C99 *was* formally defined by ISO, but strictly speaking it no longer
is.
I haven't found any C99 reference in ISO 9899 documents except from a
rationale which isn't the standard formal definition.
Post by Keith Thompson
(The terms "C89", "C90", "C99", and "C11" are informal names, not
formally defined by any standard document as far as I know; I don't
know whether that's what the previous poster was referring to.)
In fact you've gone too far in the details and that wasn't my point.
C99 is an informal term, the corresponding formal term is ISO/IEC 9899:1999. As an informal term, the term C99 does not appear anywhere in any version of the C standard. But you just said that this distinction between the informal name and the formal name isn't your point. If you ever looked at a copy of ISO/IEC 9899:1999m you should have found that it refers to itself by that name at the top of every single odd-numbered page. So, when you say you didn't find any references to C99 in any ISO 9899 document, what exactly were you looking for?

The C2011 standard also refers to ISO/IEC 9899:1999, giving it as the name of the standard superceded by C2011.

Note: I'm claiming slightly more than I can actually prove here. C99 is the only official version of the standard I have ever purchased, but I managed to lose my only copy of it in a disk crash. So I can't be sure that it has a copy of it's own name on every odd-numbered page - but that does seem to be the convention used in various draft versions of the standard that I do have a copy of. Oddly enough, n1256.pdf confusingly labels itself IOS/IEC 9899:TC3, which is an entirely different document. But what can you expect of a document that claims to have been completed on "Septermber 7, 2007" (sic)?
GOTHIER Nathan
2017-05-14 02:49:10 UTC
Permalink
Raw Message
On Sat, 13 May 2017 18:22:57 -0700 (PDT)
Post by j***@verizon.net
C99 is an informal term, the corresponding formal term is ISO/IEC 9899:1999.
As an informal term, the term C99 does not appear anywhere in any version of
the C standard. But you just said that this distinction between the informal
name and the formal name isn't your point. If you ever looked at a copy of
ISO/IEC 9899:1999m you should have found that it refers to itself by that name
at the top of every single odd-numbered page. So, when you say you didn't find
any references to C99 in any ISO 9899 document, what exactly were you looking
for?
Only for the three characters 'C', '9', '9' in the rationale n897 and drafts
n1124/1256/1548/1570.
Post by j***@verizon.net
The C2011 standard also refers to ISO/IEC 9899:1999, giving it as the name of
the standard superceded by C2011.
Note: I'm claiming slightly more than I can actually prove here. C99 is the
only official version of the standard I have ever purchased, but I managed to
lose my only copy of it in a disk crash. So I can't be sure that it has a copy
I think I won't lose my K&R book like that.
Post by j***@verizon.net
of it's own name on every odd-numbered page - but that does seem to be the
convention used in various draft versions of the standard that I do have a copy
of. Oddly enough, n1256.pdf confusingly labels itself IOS/IEC 9899:TC3, which
is an entirely different document. But what can you expect of a document that
claims to have been completed on "Septermber 7, 2007" (sic)?
As a result K&R is still the best C reference available to most programmers.
j***@verizon.net
2017-05-14 03:23:47 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Sat, 13 May 2017 18:22:57 -0700 (PDT)
Post by j***@verizon.net
C99 is an informal term, the corresponding formal term is ISO/IEC 9899:1999.
As an informal term, the term C99 does not appear anywhere in any version of
the C standard. But you just said that this distinction between the informal
name and the formal name isn't your point. If you ever looked at a copy of
ISO/IEC 9899:1999m you should have found that it refers to itself by that name
at the top of every single odd-numbered page. So, when you say you didn't find
any references to C99 in any ISO 9899 document, what exactly were you looking
for?
Only for the three characters 'C', '9', '9' in the rationale n897 and drafts
n1124/1256/1548/1570.
So your point was, in fact, about the informal name, and not about the standard described by that name? What a pointless point.

...
Post by GOTHIER Nathan
Post by j***@verizon.net
Note: I'm claiming slightly more than I can actually prove here. C99 is the
only official version of the standard I have ever purchased, but I managed to
lose my only copy of it in a disk crash. So I can't be sure that it has a copy
I think I won't lose my K&R book like that.
Don't assume that your information's safe just because it's in hard copy. I sent six big boxes of books from California; only 3 1/2 (long story) boxes arrived in Maryland. Luckily they were insured; and because I'm the kind of person that I am, I had a) a complete list of which books were shipped in each box and b) receipts for almost every book I lost. I've also lost books because of fire damage and because a friend who was helping me move failed to secure a box of books tightly in his pick-up truck.

...
Post by GOTHIER Nathan
Post by j***@verizon.net
is an entirely different document. But what can you expect of a document that
claims to have been completed on "Septermber 7, 2007" (sic)?
As a result K&R is still the best C reference available to most programmers.
Keep in mind that the reason why n1256.pdf was never officially approved is because official approval requires a review process so thorough that it would probably have caught both of those mistakes, as well as the one known mistake in the contents of n1256.pdf. The published versions of the C standard have relatively few such mistakes (few documents that big and complicated have ever been published error-free).

K&R is an excellent teaching book, and K&R 2nd edition was updated to be compatible with the C90 standard (with a few errors, due to the fact that C90 was still evolving at the time K&R 2 was written). However, if you insist on writing code to that version of the standard, the C90 standard is still a better reference work than K&R.
GOTHIER Nathan
2017-05-14 03:40:08 UTC
Permalink
Raw Message
On Sat, 13 May 2017 20:23:47 -0700 (PDT)
Post by j***@verizon.net
So your point was, in fact, about the informal name, and not about the standard
described by that name? What a pointless point.
In fact you don't want to understand my point but that's not a surprise...
Post by j***@verizon.net
Don't assume that your information's safe just because it's in hard copy. I
sent six big boxes of books from California; only 3 1/2 (long story) boxes
arrived in Maryland. Luckily they were insured; and because I'm the kind of
person that I am, I had a) a complete list of which books were shipped in each
box and b) receipts for almost every book I lost. I've also lost books because
of fire damage and because a friend who was helping me move failed to secure a
box of books tightly in his pick-up truck.
Too bad no dog ate your bunch of books... you have silly stories to tell.
Post by j***@verizon.net
K&R is an excellent teaching book, and K&R 2nd edition was updated to be
compatible with the C90 standard (with a few errors, due to the fact that C90
was still evolving at the time K&R 2 was written). However, if you insist on
writing code to that version of the standard, the C90 standard is still a
better reference work than K&R.
Perhaps you're too old and close-minded but it seems you really have some
problems with communication omitting the "available" part of my answer.
j***@verizon.net
2017-05-14 13:42:30 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Sat, 13 May 2017 20:23:47 -0700 (PDT)
...
Post by GOTHIER Nathan
Post by j***@verizon.net
K&R is an excellent teaching book, and K&R 2nd edition was updated to be
compatible with the C90 standard (with a few errors, due to the fact that C90
was still evolving at the time K&R 2 was written). However, if you insist on
writing code to that version of the standard, the C90 standard is still a
better reference work than K&R.
Perhaps you're too old and close-minded but it seems you really have some
problems with communication omitting the "available" part of my answer.
n869.pdf, n1256.pdf, and n1570.pdf are available for free to anyone with internet access, and every single one of them (even n869.pdf) is a better reference for C than K&R, so I don't see how availability is an issue. I don't know of a legal free source for C90 itself, but then, I've never been interested in that - it never occurred to me that I could get a copy of the official standard until after work had already started on C99.
GOTHIER Nathan
2017-05-14 14:30:23 UTC
Permalink
Raw Message
On Sun, 14 May 2017 06:42:30 -0700 (PDT)
Post by j***@verizon.net
K&R is an excellent teaching book, and K&R 2nd edition was updated to be
compatible with the C90 standard (with a few errors, due to the fact that C90
was still evolving at the time K&R 2 was written). However, if you insist on
writing code to that version of the standard, the C90 standard is still a
better reference work than K&R.
n869.pdf, n1256.pdf, and n1570.pdf are available for free to anyone with
internet access, and every single one of them (even n869.pdf) is a better
reference for C than K&R, so I don't see how availability is an issue. I don't
know of a legal free source for C90 itself, but then, I've never been
interested in that - it never occurred to me that I could get a copy of the
official standard until after work had already started on C99.
You don't know how to legally access to C90 but you pretend it to be a better
source than K&R (2nd edition) widely available on sale. This is a complete non
sense! I would suggest you to see a doctor or to take your pills old man.
Keith Thompson
2017-05-14 19:40:39 UTC
Permalink
Raw Message
Post by j***@verizon.net
Post by GOTHIER Nathan
On Sat, 13 May 2017 20:23:47 -0700 (PDT)
...
Post by GOTHIER Nathan
Post by j***@verizon.net
K&R is an excellent teaching book, and K&R 2nd edition was updated
to be compatible with the C90 standard (with a few errors, due to
the fact that C90 was still evolving at the time K&R 2 was
written). However, if you insist on writing code to that version of
the standard, the C90 standard is still a better reference work
than K&R.
Perhaps you're too old and close-minded but it seems you really have some
problems with communication omitting the "available" part of my answer.
n869.pdf, n1256.pdf, and n1570.pdf are available for free to anyone
with internet access, and every single one of them (even n869.pdf) is
a better reference for C than K&R, so I don't see how availability is
an issue. I don't know of a legal free source for C90 itself, but
then, I've never been interested in that - it never occurred to me
that I could get a copy of the official standard until after work had
already started on C99.
I'm not sure there's any good reason to refer to n869.pdf apart
from historical curiosity. Both N869 and N1256 are drafts of
the C99 standard. N869 is a committee draft published 1999-01-18,
before the official C99 standard was published. N1256 is a committee
draft published 2007-09-07 ("Septermber 7, 2007"); it includes the
C99 standard plus the three Technical Corrigenda.

The best free resource I know of for the C89/C90 standard is
http://flash-gordon.me.uk/ansi.c.txt, a plain-text draft of the 1989
ANSI C standard. (I also have a PDF copy of the ISO C90 standard
that I paid for, but I don't think it's available anymore.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Robert Wessel
2017-05-14 05:18:53 UTC
Permalink
Raw Message
On Sun, 14 May 2017 04:49:10 +0200, GOTHIER Nathan
Post by GOTHIER Nathan
On Sat, 13 May 2017 18:22:57 -0700 (PDT)
Post by j***@verizon.net
C99 is an informal term, the corresponding formal term is ISO/IEC 9899:1999.
As an informal term, the term C99 does not appear anywhere in any version of
the C standard. But you just said that this distinction between the informal
name and the formal name isn't your point. If you ever looked at a copy of
ISO/IEC 9899:1999m you should have found that it refers to itself by that name
at the top of every single odd-numbered page. So, when you say you didn't find
any references to C99 in any ISO 9899 document, what exactly were you looking
for?
Only for the three characters 'C', '9', '9' in the rationale n897 and drafts
n1124/1256/1548/1570.
The cover of ISO/IEC 9899:1999 contains the text:

"INTERNATIONAL
STANDARD
ISO/IEC
9899
Second edition
1999-12-01
Programming languages — C
Langages de programmation — C"

If you can't get the informal name "C99" out of that, I'm not sure I
can help.

And, as might be expected, the C11 standard changes the above text to
third edition and a 2011 date.
GOTHIER Nathan
2017-05-14 12:45:34 UTC
Permalink
Raw Message
On Sun, 14 May 2017 00:18:53 -0500
Post by Robert Wessel
If you can't get the informal name "C99" out of that, I'm not sure I
can help.
I should have written the 'C', '9', '9' sequence or the "C99" string but you
don't care. You only answer some sh!t to make sh!t. If you only have rotten
comments to provide, I would suggest you to put them in your garden and come
later with good ones.
Tim Rentsch
2017-05-14 07:08:25 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Ben Bacarisse
Post by bartc
Post by Ben Bacarisse
Not me. I prefer declarations all tucked away in a corner so
they don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't
clutter up the rest of the code. That way I have smaller regions
of code to verify.
Then it means having to analyse every line back to the start of
the function to find the declaration of some variable. Just in
case it might have been declared somewhere in between.
When you just put all the declarations at the top of a function you
have to check every line for occurrences of every variable (if you
are doing any sort of semi-formal reasoning about your code), but
both this and your remark, whist being genuine problems with each
approach, are largely trivial in that there are simple tools to
help in both cases.
It's hard to put into words why I find it so very much more
comfortable to do it my way. I suspect a lot of it comes down to
the fact that we think about code in very different ways, but here
I'm currently in the process of replacing systematically on our
porject the style of declaration, from the standard C way to the
new C99 in-code declarations. What I have notices during that
process is that
- the code always gets shorter (1 line of declaration +1 line first
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up
in big functions.
- for loop declared variables allows to copy paste code more easily.
- refactoring long functions in to several smaller ones becomes
order of magnitude easier if you declare the variable where it is
used. I was surprized to see how often a variable was declared at
the beginning and only used twice at the end of the function in a
very unlikely error path.
The funny thing is that doing that has brought the need for the if(
with declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
I have read through the comments in this thread with much
interest. Sometime after seeing this posting I thought I would
go through some code on a similar venture to the one described
above. I have enough experience with both styles so that I
didn't feel a need to make changes, but I wanted to see where and
how big the differences would be. I looked at sources from two
different projects: one, a fair number of functions that had
been written under C90 rules; and two, to add some perspective,
a single, rather complex, function that had been written under
C99 rules.

The first case had 36 functions, averaging about 22 lines each
but with a standard deviation of about 23 lines. (Those counts
include only the function body, not the function declaration
lines or the trailing close brace line.) The median length was
16 lines. The ten longest functions had 30, 34, 34, 37, 40, 49,
59, 83, and 98 lines respectively.

I found a few instances where "within statements" declarations
looked like an improvement: one regular declaration, two as
part of for() loops (and two other plausible ones). There were
three instances where C99 initializer rules would have helped
(ie, but keeping C90 declaration placement).

Balancing that, there were just as many instances (I didn't
count these exactly) where a "within statements" declaration
was possible but looked like it gave a worse result, either
because of line length overflow or adaptability of code to
potential future changes, or circumstances that related to
those conditions. (Note added in editing: in most cases the
question didn't come up, either because the declaration already
had an initializer, or because it couldn't have one (ie, that
did anything useful) for some reason.)

What mattered much more was not where declarations were put but
how long the functions are. All the functions longer than about
30 or 35 lines clearly are in need of some recomposing (which in
fact looks fairly straightforward to do in this case). So that
seems like the high-order bit here.

The second case was interesting in a different way, partly
because it was written under C99 rules and already made use of a
"within-statements" initializing declaration. The code under
consideration is a single function, somewhat complicated but not
so large that breaking into smaller pieces is called for.

What makes the function interesting is four related variables,
let me call them a, b, x, and y. In the main flow of the
algorithm, x and y are set based on the value of a parameter, and
a and b are then set based on the values of x and y. However,
for a small subset of input values, there is fast path that only
sets 'a' (and then falls into some subsequent code). Practically
speaking the variable a must be declared before being given its
initial value. The question is what to do about the other three
related variables. Should they be declared parallel to a,
reflecting their relationship to a in the main line of the
algorithm? Or should they be declared separately, in only the
"slow path" of the algorithm, even though that is the predominate
case? (Note: the fast path is solely about performance - the
slow path always works, it just runs slower than the fast path.)
The code could be written either way. Ultimately I decided that
it made more sense to declare a, b, x, and y all together, even
though b, x, and y could have been declared more locally (and
clearly the function being fairly small played a significant
part in that decision). I think either decision is plausible, as
they both have their plusses and minuses, but on balance grouping
them all together seems like a better fit. I expect other people
would make a different decision.

After all of that, what are my conclusions? I think the main
conclusions are these:

One: I normally read function bodies "all at once" rather
than a line at a time. For me reading a function means
getting the whole function body in my head so I can think
about all of it at the same time.

Two: As both a cause and effect of the above, I very strongly
prefer functions be kept short, and that have been kept short.

Three: If function bodies are short, declaration placement
doesn't matter so much.

Four: There are several competing factors for where to put
declarations. Some favor putting declarations in one place,
some favor a different placement. Neither choice is right
in all cases; nor does one seem to predominate.

Five: As a corollary to (three) and (four), if refactoring
needs to be done, focusing on function length is more likely
to give a better ROI than moving declarations around.

And now I look forward to hearing all the kind responses and
rebuttals. :)
Patrick.Schluter
2017-05-14 08:51:39 UTC
Permalink
Raw Message
<snip>
Post by Tim Rentsch
I have read through the comments in this thread with much
interest. Sometime after seeing this posting I thought I would
go through some code on a similar venture to the one described
above. I have enough experience with both styles so that I
didn't feel a need to make changes, but I wanted to see where and
how big the differences would be. I looked at sources from two
different projects: one, a fair number of functions that had
been written under C90 rules; and two, to add some perspective,
a single, rather complex, function that had been written under
C99 rules.
The first case had 36 functions, averaging about 22 lines each
but with a standard deviation of about 23 lines. (Those counts
include only the function body, not the function declaration
lines or the trailing close brace line.) The median length was
16 lines. The ten longest functions had 30, 34, 34, 37, 40, 49,
59, 83, and 98 lines respectively.
I found a few instances where "within statements" declarations
looked like an improvement: one regular declaration, two as
part of for() loops (and two other plausible ones). There were
three instances where C99 initializer rules would have helped
(ie, but keeping C90 declaration placement).
Balancing that, there were just as many instances (I didn't
count these exactly) where a "within statements" declaration
was possible but looked like it gave a worse result, either
because of line length overflow or adaptability of code to
potential future changes, or circumstances that related to
those conditions. (Note added in editing: in most cases the
question didn't come up, either because the declaration already
had an initializer, or because it couldn't have one (ie, that
did anything useful) for some reason.)
What mattered much more was not where declarations were put but
how long the functions are. All the functions longer than about
30 or 35 lines clearly are in need of some recomposing (which in
fact looks fairly straightforward to do in this case). So that
seems like the high-order bit here.
The second case was interesting in a different way, partly
because it was written under C99 rules and already made use of a
"within-statements" initializing declaration. The code under
consideration is a single function, somewhat complicated but not
so large that breaking into smaller pieces is called for.
What makes the function interesting is four related variables,
let me call them a, b, x, and y. In the main flow of the
algorithm, x and y are set based on the value of a parameter, and
a and b are then set based on the values of x and y. However,
for a small subset of input values, there is fast path that only
sets 'a' (and then falls into some subsequent code). Practically
speaking the variable a must be declared before being given its
initial value. The question is what to do about the other three
related variables. Should they be declared parallel to a,
reflecting their relationship to a in the main line of the
algorithm? Or should they be declared separately, in only the
"slow path" of the algorithm, even though that is the predominate
case? (Note: the fast path is solely about performance - the
slow path always works, it just runs slower than the fast path.)
The code could be written either way. Ultimately I decided that
it made more sense to declare a, b, x, and y all together, even
though b, x, and y could have been declared more locally (and
clearly the function being fairly small played a significant
part in that decision). I think either decision is plausible, as
they both have their plusses and minuses, but on balance grouping
them all together seems like a better fit. I expect other people
would make a different decision.
After all of that, what are my conclusions? I think the main
One: I normally read function bodies "all at once" rather
than a line at a time. For me reading a function means
getting the whole function body in my head so I can think
about all of it at the same time.
Two: As both a cause and effect of the above, I very strongly
prefer functions be kept short, and that have been kept short.
Three: If function bodies are short, declaration placement
doesn't matter so much.
Four: There are several competing factors for where to put
declarations. Some favor putting declarations in one place,
some favor a different placement. Neither choice is right
in all cases; nor does one seem to predominate.
Five: As a corollary to (three) and (four), if refactoring
needs to be done, focusing on function length is more likely
to give a better ROI than moving declarations around.
And now I look forward to hearing all the kind responses and
rebuttals. :)
No rebuttal on my part. What you write is completely sensible and true.

As I said somewhere else in the thread and I should have put it in the
comment above, my observation to systematically transform our code from
pre-C99 style to on-the-spot declaration was that the positive effect
was partially due to the code review happening automatically during the
refactoring.

What I also didn't mention is that the impact varied depending on the
author of the initial code. Our code base goes back to the 90s and the
code style and quality varies immensely between the different
developpers who were on the project. Depending on who wrote initially
the function the changes in the declarations could go from inexistant to
very profund. It never has a negative impact because in the case it had
one you wouldn't do the change in first place.
Tim Rentsch
2017-05-14 21:32:54 UTC
Permalink
Raw Message
Post by Ben Bacarisse
<snip>
Post by Tim Rentsch
I have read through the comments in this thread with much
interest. [...]
After all of that, what are my conclusions? [...]
And now I look forward to hearing all the kind responses and
rebuttals. :)
No rebuttal on my part. What you write is completely sensible and true.
Thank you, that is always nice to hear.
Post by Ben Bacarisse
As I said somewhere else in the thread and I should have put it in the
comment above, my observation to systematically transform our code
from pre-C99 style to on-the-spot declaration was that the positive
effect was partially due to the code review happening automatically
during the refactoring.
Ah, thank you for repeating that; I think I missed it earlier.
Post by Ben Bacarisse
What I also didn't mention is that the impact varied depending on the
author of the initial code. Our code base goes back to the 90s and the
code style and quality varies immensely between the different
developpers who were on the project. Depending on who wrote initially
the function the changes in the declarations could go from inexistant
to very profund. It never has a negative impact because in the case it
had one you wouldn't do the change in first place.
Interesting. I'm glad you followed up, these extra comments
definitely add some facets that I didn't realize before.
Ben Bacarisse
2017-05-14 10:37:32 UTC
Permalink
Raw Message
Tim Rentsch <***@alumni.caltech.edu> writes:
<snip>
Post by Tim Rentsch
I have read through the comments in this thread with much
interest. Sometime after seeing this posting I thought I would
go through some code on a similar venture to the one described
above. I have enough experience with both styles so that I
didn't feel a need to make changes, but I wanted to see where and
how big the differences would be. I looked at sources from two
different projects: one, a fair number of functions that had
been written under C90 rules; and two, to add some perspective,
a single, rather complex, function that had been written under
C99 rules.
Did any of the code strictly follow bartc's rules? He abjures even
declarations in blocks other than the function body.

<snip the details>
Post by Tim Rentsch
After all of that, what are my conclusions? I think the main
One: I normally read function bodies "all at once" rather
than a line at a time. For me reading a function means
getting the whole function body in my head so I can think
about all of it at the same time.
Two: As both a cause and effect of the above, I very strongly
prefer functions be kept short, and that have been kept short.
Three: If function bodies are short, declaration placement
doesn't matter so much.
Four: There are several competing factors for where to put
declarations. Some favor putting declarations in one place,
some favor a different placement. Neither choice is right
in all cases; nor does one seem to predominate.
Five: As a corollary to (three) and (four), if refactoring
needs to be done, focusing on function length is more likely
to give a better ROI than moving declarations around.
I've not done this exercise, but I think I'd probably come to the same
conclusions. I might have a different view of point five if the code
had no declarations in nested scopes (i.e. was full-on bartc style), but
even then I suspect I'd be more interested in function size.

<snip>
--
Ben.
bartc
2017-05-14 12:40:31 UTC
Permalink
Raw Message
Post by Ben Bacarisse
Did any of the code strictly follow bartc's rules? He abjures even
declarations in blocks other than the function body.
Apart from the objections I've already given, there is another reason I
tend to put declarations at the top of a function.

I sometimes share or port code between a language that requires static
declarations, and a dynamic language that doesn't. That latter one
doesn't require declarations for local variables (and when given, they
have function scope).

So it is useful to keep code uncluttered of such declarations. This is
the case more generally too, for separating an algorithm from the fiddly
details of its implementation.

But C-style block scopes also introduce another factor, which is needing
to match a particular identifier with a specific declaration and a
certain scope. This is an extra distraction.
--
bartc
Manfred
2017-05-14 14:03:11 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Did any of the code strictly follow bartc's rules? He abjures even
declarations in blocks other than the function body.
Apart from the objections I've already given, there is another reason I
tend to put declarations at the top of a function.
I sometimes share or port code between a language that requires static
declarations, and a dynamic language that doesn't. That latter one
doesn't require declarations for local variables (and when given, they
have function scope).
I think this is an argument that applies to porting between languages
with different features, so it looks to me as pretty specific to
motivate some general coding style rule. I mean, it may be very well
motivated in some specific cases (e.g. when the targeted/targetable
hardware poses significant constraints on code), but not so much as a
general rule.
Post by bartc
So it is useful to keep code uncluttered of such declarations. This is
the case more generally too, for separating an algorithm from the fiddly
details of its implementation.
I think, FWIW, that the variables and their types required by an
algorithm are an essential part of the algorithm itself, better kept
coupled with it. If you have a function whose whole body is the
implementation of a single algorithm (good practice), then I agree with
you that its key data is better declared altogether at the top of it
(btw, needless to say, since in this case typical usage of this data
spans the whole function body).

Data which is classifiable as "fiddly details" is most commonly of the
kind of temp values which are best kept as local as possible, IMHO.
Post by bartc
But C-style block scopes also introduce another factor, which is needing
to match a particular identifier with a specific declaration and a
certain scope. This is an extra distraction.
In many cases, for me this would not be a distraction, since the
"certain scope" would be the /current/ scope.
bartc
2017-05-14 15:04:38 UTC
Permalink
Raw Message
Post by Manfred
Post by bartc
So it is useful to keep code uncluttered of such declarations. This is
the case more generally too, for separating an algorithm from the
fiddly details of its implementation.
I think, FWIW, that the variables and their types required by an
algorithm are an essential part of the algorithm itself, better kept
coupled with it.
The algorithm will still have the variables (assuming you are using some
universally understood notation), but the types can usually be inferred
from the initial assignments or shown in an accompanying, but separate,
annotation.

If you started putting C++-style declarations amongst the code then you
can forget about to trying to easily understand what it's trying to do.
Post by Manfred
Post by bartc
But C-style block scopes also introduce another factor, which is
needing to match a particular identifier with a specific declaration
and a certain scope. This is an extra distraction.
In many cases, for me this would not be a distraction, since the
"certain scope" would be the /current/ scope.
{ int a;
{ int b,A;
{ int c;
a = b + c;
int a,b,c;
}

}
}

What's the 'current scope' on the a=b+c line? It's not tidily
delineated. You have to keep constructing such an enclosing envelope,
and it's associated context of declared entities, for every expression.
--
bartc
bartc
2017-05-14 15:27:01 UTC
Permalink
Raw Message
Post by bartc
{ int a;
{ int b,A;
{ int c;
a = b + c;
int a,b,c;
Actually the last c is not allowed as there are two declarations of it
without intervening braces.

Which highlights another problem as you have to look more carefully to
see if repeated declarations like this are legal or not.
Tim Rentsch
2017-05-14 22:26:50 UTC
Permalink
Raw Message
Post by Ben Bacarisse
<snip>
Post by Tim Rentsch
I have read through the comments in this thread with much
interest. Sometime after seeing this posting I thought I would
go through some code on a similar venture to the one described
above. I have enough experience with both styles so that I
didn't feel a need to make changes, but I wanted to see where and
how big the differences would be. I looked at sources from two
different projects: one, a fair number of functions that had
been written under C90 rules; and two, to add some perspective,
a single, rather complex, function that had been written under
C99 rules.
Did any of the code strictly follow bartc's rules? He abjures even
declarations in blocks other than the function body.
No, the code routinely made use of variable declarations in
nested blocks, in nearly all cases where the function's
structure allowed doing so. (Also, whether by coincidence or
not, all those nested declarations had initializers.)
Post by Ben Bacarisse
<snip the details>
Post by Tim Rentsch
After all of that, what are my conclusions? I think the main
One: I normally read function bodies "all at once" rather
than a line at a time. For me reading a function means
getting the whole function body in my head so I can think
about all of it at the same time.
Two: As both a cause and effect of the above, I very strongly
prefer functions be kept short, and that have been kept short.
Three: If function bodies are short, declaration placement
doesn't matter so much.
Four: There are several competing factors for where to put
declarations. Some favor putting declarations in one place,
some favor a different placement. Neither choice is right
in all cases; nor does one seem to predominate.
Five: As a corollary to (three) and (four), if refactoring
needs to be done, focusing on function length is more likely
to give a better ROI than moving declarations around.
I've not done this exercise, but I think I'd probably come to the same
conclusions. I might have a different view of point five if the code
had no declarations in nested scopes (i.e. was full-on bartc style), but
even then I suspect I'd be more interested in function size.
If I were looking at code that never used declarations in nested
scopes, even in places where it clearly could have, there's a
good chance I would take a first pass over the code to do that
(this is assuming of course some sort of refactoring is on the
agenda). My reasoning is (a) it's low cost, (b) it's low risk,
and (c) is likely to help subsequent changes be easier and more
reliable. Without actually trying it I can't say for sure, but
I suspect that would hold over a broad range of function size
distribution, ie, as long as functions were large enough so that
they had more than just a few nested scopes as candidates.
Patrick.Schluter
2017-05-14 09:09:59 UTC
Permalink
Raw Message
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that
- the code always gets shorter (1 line of declaration +1 line first
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
- for loop declared variables allows to copy paste code more easily.
- refactoring long functions in to several smaller ones becomes order of
magnitude easier if you declare the variable where it is used. I was
surprized to see how often a variable was declared at the beginning and
only used twice at the end of the function in a very unlikely error path.
The funny thing is that doing that has brought the need for the if( with
declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
What I forgot to mention there were some cases where that transformation
uncovered subtle bugs. The bug could have also been diagnosticised by
the compiler if the variable hadn't been initialised, the position of
the declaration was not the problem in that case, only the initial value.

By systematically initialising a variable in the head of a function (to
0 or NULL), the compiler was not able to do a proper life time analysis
of the variable and wouldn't emit the warning that a variable was used
before it had a proper value.

These cases were not frequent but often enough that I start to think
that often given advice to always initialise auto variables to not be
such a good idea.

The C99 declaration as you go has the advantage that you can now bind
the declaration of the variable with the right initial value. A thing
that was not always possible before (vla, variables in initialisers and
compound statements help also in these cases).
GOTHIER Nathan
2017-05-14 13:05:08 UTC
Permalink
Raw Message
On Sun, 14 May 2017 11:09:59 +0200
Post by Patrick.Schluter
These cases were not frequent but often enough that I start to think
that often given advice to always initialise auto variables to not be
such a good idea.
The bad idea is to allocate an useless memory space filled with dumb data at the
wrong time. Thus the necessity to initialize any object only when it should
have to be (i.e. the first time) at the best scope (cf. recursion).
Tim Rentsch
2017-05-14 21:55:57 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Patrick.Schluter
I'm currently in the process of replacing systematically on our porject
the style of declaration, from the standard C way to the new C99 in-code
declarations. What I have notices during that process is that
- the code always gets shorter (1 line of declaration +1 line first
usage gets replaced by 1 line of declaration with initialisation.
- this often leads to some optimisations as very often the old
declarations initialised the variables for no reason.
- I've found several bugs in the code where variables got mixed up in
big functions.
- for loop declared variables allows to copy paste code more easily.
- refactoring long functions in to several smaller ones becomes order of
magnitude easier if you declare the variable where it is used. I was
surprized to see how often a variable was declared at the beginning and
only used twice at the end of the function in a very unlikely error path.
The funny thing is that doing that has brought the need for the if( with
declaration as the pattern of
type var = call();
if(var == somethin) callsomething(var);
is really very frequent.
What I forgot to mention there were some cases where that
transformation uncovered subtle bugs. The bug could have also been
diagnosticised by the compiler if the variable hadn't been
initialised, the position of the declaration was not the problem in
that case, only the initial value.
By systematically initialising a variable in the head of a function
(to 0 or NULL), the compiler was not able to do a proper life time
analysis of the variable and wouldn't emit the warning that a variable
was used before it had a proper value.
These cases were not frequent but often enough that I start to think
that often given advice to always initialise auto variables to not be
such a good idea.
My practice is not to initialize variables with "empty" values,
for just this very reason.
Post by Patrick.Schluter
The C99 declaration as you go has the advantage that you can now bind
the declaration of the variable with the right initial value.
Something I think is interesting is that this has always been
possible, by starting a new block, but even so it is (and was)
almost never done. To me that suggests that the capability
isn't so important as some would have us believe.

Also, I believe it's possible to initialize variables with their
"right" initial values, even following C90 declaration placement,
a lot more often than most people do, by taking advantage of
conditional operators (and sometimes other "tricks"). A big part
of the problem is not technical but cultural.
Post by Patrick.Schluter
A thing
that was not always possible before (vla, variables in initialisers
and compound statements help also in these cases).
Compound statements - no question.

VLA - they avoid having to use malloc() - what else do
they do (if anything)?

Variables in initializers - do you mean non-constant values in
aggregate initializers? If not then what do you mean?
Alan Mackenzie
2017-05-12 16:25:26 UTC
Permalink
Raw Message
Post by bartc
Post by Ben Bacarisse
Post by bartc
Not me. I prefer declarations all tucked away in a corner so they
don't clutter up the code.
I prefer to have my scopes all tucked away so the names don't clutter up
the rest of the code. That way I have smaller regions of code to verify.
Then it means having to analyse every line back to the start of the
function to find the declaration of some variable. Just in case it might
have been declared somewhere in between.
With the right tool, i.e. an editor that highlights declarations, this
is not an onerous task.

[ .... ]
Post by bartc
--
bartc
--
Alan Mackenzie (Nuremberg, Germany).
j***@gmail.com
2017-05-10 23:45:46 UTC
Permalink
Raw Message
Post by bartc
Post by Thiago Adams
C++ 17, has now a new if.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html
if ( for-init-statement condition ) statement
is equivalent to
{
for-init-statement
if ( condition ) statement
}
and
if ( for-init-statement condition ) statement else statement
is equivalent to
{
for-init-statement
if ( condition ) statement else statement
}
Would you like to see this if on C?
Not me. I prefer declarations all tucked away in a corner so they don't
clutter up the code.
People complain about Hungarian notation but this doesn't seem much
different.
Besides, this can be done now with {} either surrounding the if
statement (assuming the scope extends to the end of the second
statement), or inside the condition using the gcc extension.
--
bartc
{ int ch;
if ( ( ch = getchar() ) == EOF )
break;
...
buffer[ i++ ] = ch;
...
}

As opposed to

if ( getchar() == EOF ) { ... }

If I'm going to go to the trouble of explicitly saving a result, I think I want the result.

If I want to throw it away, I want to throw it away.

On the for loop, providing explicit loop variables does make the syntax useful.
--
Joel Rees

Ranting randomly:
http://reiisi.blogspot.com
Thiago Adams
2017-05-11 12:07:17 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
[...]
One more:

Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf

int i = 1'000'000;

What I find weird is that the position of ' is not verified.

"An integer literal is a sequence of digits that has no period or exponent part, with optional
separating single quotes that are ignored when determining its value"
Thiago Adams
2017-05-11 12:10:05 UTC
Permalink
Raw Message
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Binary Literals in the C++ Core Language
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf

int i = 0b1100;

(I liked this)
David Brown
2017-05-11 12:29:17 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Binary Literals in the C++ Core Language
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf
int i = 0b1100;
(I liked this)
Many compilers support that as an extension (in C and C++). Indeed, C++
picked it up as a feature that existing tools had supported for years,
users found useful, and there were no conflicts with anything else in
the language. So it was a cheap and easy addition to the C++ standards.

Apparently in the C world, we are supposed to define our own macros of
various levels of ugliness and odd restrictions, and use them. Since it
is /possible/ to use macros to write binary literals, it does not need
to be added to the language.


Yes, /I/ would like to see it added to C - and I truly believe it would
have negligible costs. I appreciate that one of the aims of C is to
keep the language small and stable, and let C++ be the relative with all
the latest bells and whistles. But this would be a couple of paragraphs
to add to the standard - and /nothing/ to change in the major compiler
implementations.

Binary constants are easier to write when there is a digit separator.
The choice of ' is not pretty, but all the better alternatives have
disadvantages. I'd be happy to see that in C too, and would use it
occasionally.

Both these changes are zero cost to the user - the don't affect existing
correct code, they don't introduce new ways to get things wrong, they
can be safely ignored if you don't need them, and they are easily
understood when you see them for the first time.
Keith Thompson
2017-05-11 16:10:45 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Verified how?
Post by Thiago Adams
"An integer literal is a sequence of digits that has no period or
exponent part, with optional separating single quotes that are ignored
when determining its value"
Separating every 3 digits, counting from the low-order digit, is not the
only possible pattern. I believe that a different convention is used in
India (I don't remember the details). In a context where the
conventional 3-digit grouping is desirable, any deviation should be
reasonably obvious to the reader.

And grouping by 4 digits is likely to be common for hexadecimal and
binary.

(I personally wish that the syntax had used underscores, but that was
precluded by C++ user-defined literals.)
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Thiago Adams
2017-05-11 16:49:51 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Verified how?
Post by Thiago Adams
"An integer literal is a sequence of digits that has no period or
exponent part, with optional separating single quotes that are ignored
when determining its value"
Separating every 3 digits, counting from the low-order digit, is not the
only possible pattern. I believe that a different convention is used in
India (I don't remember the details). In a context where the
conventional 3-digit grouping is desirable, any deviation should be
reasonably obvious to the reader.
And grouping by 4 digits is likely to be common for hexadecimal and
binary.
(I personally wish that the syntax had used underscores, but that was
precluded by C++ user-defined literals.)
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.

If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
bartc
2017-05-11 17:51:15 UTC
Permalink
Raw Message
Post by Thiago Adams
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.
If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
That doesn't really work. There are a million different editors and
syntax highlighters. The few I've tried will not automatically insert
separators on numbers. It would create problems anyway on mono-spaced
fonts as things will no longer line up. And sometimes you want
separators, and sometimes you don't. Or in a different pattern.

But if the language allows you to, then you can add explicit separators
and EVERY editor will display them. And exactly where you want them.

So I might want to write a binary number like this: 2x10'110'001 so that
the fields match some format. (Or it might be 0b in C.)
Post by Thiago Adams
I guess the motivation was avoid mistakes.
Yes, in writing the numbers in the first place. How will an editor know
when to insert the separators as you write 1,234,567? Assuming you
start writing from left to right:

You enter so far: The editor shows:

1 1
12 12
123 123
1234 1'234
12345 12,345

Now it's out of sync for a couple of characters, which will be
confusing. Much easier to do it 'manually'.
--
bartc
Thiago Adams
2017-05-11 18:19:50 UTC
Permalink
Raw Message
Post by bartc
Post by Thiago Adams
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.
If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
That doesn't really work. There are a million different editors and
syntax highlighters. The few I've tried will not automatically insert
separators on numbers. It would create problems anyway on mono-spaced
fonts as things will no longer line up. And sometimes you want
separators, and sometimes you don't. Or in a different pattern.
But if the language allows you to, then you can add explicit separators
and EVERY editor will display them. And exactly where you want them.
My idea was to group using colors.
How uses an source editor without colors today? (I am afraid to ask :D)

I don't think this digit groups are bad, but maybe they
are not too good to add to the language.
Scott Lurndal
2017-05-11 18:31:24 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by bartc
Post by Thiago Adams
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.
If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
That doesn't really work. There are a million different editors and
syntax highlighters. The few I've tried will not automatically insert
separators on numbers. It would create problems anyway on mono-spaced
fonts as things will no longer line up. And sometimes you want
separators, and sometimes you don't. Or in a different pattern.
But if the language allows you to, then you can add explicit separators
and EVERY editor will display them. And exactly where you want them.
My idea was to group using colors.
How uses an source editor without colors today? (I am afraid to ask :D)
I would say a large fraction of programmers don't use
source editors with colors _all the time_. Particularly
folks who still use vi (as opposed to vim).

Verilog number formats:

[<sign>][<size-in-bits>]'<base><digits>

where base is b (2), o(8), d(10), h(16). Digits can be grouped with underscore.
The digit 'z' indicates a high-impedence signal, while 'x' indicates unknown/dont-care

sample:
8'hA0 (8-bit decimal value 160)
64'h1234_5678_9abc_def0

und so weiter.
Keith Thompson
2017-05-11 18:59:10 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Keith Thompson
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Verified how?
Post by Thiago Adams
"An integer literal is a sequence of digits that has no period or
exponent part, with optional separating single quotes that are ignored
when determining its value"
Separating every 3 digits, counting from the low-order digit, is not the
only possible pattern. I believe that a different convention is used in
India (I don't remember the details). In a context where the
conventional 3-digit grouping is desirable, any deviation should be
reasonably obvious to the reader.
And grouping by 4 digits is likely to be common for hexadecimal and
binary.
(I personally wish that the syntax had used underscores, but that was
precluded by C++ user-defined literals.)
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.
If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
Not everyone uses highlighting text editors.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
David Kleinecke
2017-05-11 19:58:08 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Thiago Adams
Post by Keith Thompson
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Verified how?
Post by Thiago Adams
"An integer literal is a sequence of digits that has no period or
exponent part, with optional separating single quotes that are ignored
when determining its value"
Separating every 3 digits, counting from the low-order digit, is not the
only possible pattern. I believe that a different convention is used in
India (I don't remember the details). In a context where the
conventional 3-digit grouping is desirable, any deviation should be
reasonably obvious to the reader.
And grouping by 4 digits is likely to be common for hexadecimal and
binary.
(I personally wish that the syntax had used underscores, but that was
precluded by C++ user-defined literals.)
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.
If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
Not everyone uses highlighting text editors.
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
bartc
2017-05-11 20:18:17 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by Keith Thompson
Post by Thiago Adams
Post by Keith Thompson
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Verified how?
Post by Thiago Adams
"An integer literal is a sequence of digits that has no period or
exponent part, with optional separating single quotes that are ignored
when determining its value"
Separating every 3 digits, counting from the low-order digit, is not the
only possible pattern. I believe that a different convention is used in
India (I don't remember the details). In a context where the
conventional 3-digit grouping is desirable, any deviation should be
reasonably obvious to the reader.
And grouping by 4 digits is likely to be common for hexadecimal and
binary.
(I personally wish that the syntax had used underscores, but that was
precluded by C++ user-defined literals.)
Yes, 3-digit grouping.
I guess the motivation was avoid mistakes.
If is just to see better, why not give the job for text editors?
They can create some distinction on rendering.
Not everyone uses highlighting text editors.
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
I would have thought that it needed to recognise and expand macros too.
But I'm not sure that's possible because that can depend on conditional
code.

And not all conditions are known because some are external so the editor
won't know about them. (They might be in a header the editor has no
access to, or it hasn't been created yet, or they are a compiler option.)
--
bartc
Thiago Adams
2017-05-11 20:45:56 UTC
Permalink
Raw Message
On Thursday, May 11, 2017 at 4:58:15 PM UTC-3, David Kleinecke wrote:
[...]
Post by David Kleinecke
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
Yes they do this and much more.
Ian Collins
2017-05-12 08:08:44 UTC
Permalink
Raw Message
Post by David Kleinecke
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
You haven't looked very hard then!
--
Ian
Malcolm McLean
2017-05-12 08:37:01 UTC
Permalink
Raw Message
Post by Ian Collins
Post by David Kleinecke
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
You haven't looked very hard then!
XCode's editor does a full semantic pass over C++ source.
You even have smart autocomplete - type structure variable,
and dot, and a list of members pops up.
bartc
2017-05-12 11:08:10 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by Ian Collins
Post by David Kleinecke
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
You haven't looked very hard then!
XCode's editor does a full semantic pass over C++ source.
You even have smart autocomplete - type structure variable,
and dot, and a list of members pops up.
That's XCode.

What about a thousand other products that don't do that?

You can't decide whether or not to add a language feature based on the
capabilities of a handful of smart editors.

That fact is that if I upload any C code to pastebin or github now, they
won't insert separators in my numbers, even if the tool I use myself
does so (it doesn't).

Sometime this is about making things easier for other people. If every
shared fragment of C also came with a working XCode renderer so everyone
could view the code in the same way, that would be great. But that isn't
yet the case.

You would hope however that every text viewer could show ASCII.
--
bartc
David Brown
2017-05-12 13:31:27 UTC
Permalink
Raw Message
Post by bartc
Post by Malcolm McLean
Post by Ian Collins
Post by David Kleinecke
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
You haven't looked very hard then!
XCode's editor does a full semantic pass over C++ source.
You even have smart autocomplete - type structure variable,
and dot, and a list of members pops up.
That's XCode.
What about a thousand other products that don't do that?
What about the dozens of other editors that /do/ have something similar?
The ones that most professional programmers use all the time (Eclipse,
MSVS, Netbeans, emacs, vim, CLion, jedit, programmer's notepad,
notepad++, etc.) have excellent C syntax highlighting. I can't tell you
off-hand if they /all/ highlight typedef names, but I expect they do.
Post by bartc
You can't decide whether or not to add a language feature based on the
capabilities of a handful of smart editors.
"Add a language feature"? How long has C had typedef? 40 years?

And if you are working as a programmer and don't have a decent editor,
it is /your/ fault.
Post by bartc
That fact is that if I upload any C code to pastebin or github now, they
won't insert separators in my numbers, even if the tool I use myself
does so (it doesn't).
I believe you have got your Usenet sub-threads mixed up. The issue here
is David K's absurd idea that there are no editors that highlight
typedef names.

Syntax highlighting of new features /is/ an issue - you are right there.
In particular, when adding a new language feature it is helpful if
existing popular editors do not mark it as a syntax error.

If ' were added to C as a digit separator, it would probably not take
long before leading editors and websites accepted it - after all, they
accept it in C++.
Post by bartc
Sometime this is about making things easier for other people. If every
shared fragment of C also came with a working XCode renderer so everyone
could view the code in the same way, that would be great. But that isn't
yet the case.
You would hope however that every text viewer could show ASCII.
Do you know of any that can't?
Malcolm McLean
2017-05-12 14:03:44 UTC
Permalink
Raw Message
Post by David Brown
And if you are working as a programmer and don't have a decent editor,
it is /your/ fault.
Not always.
For example I'm paying around with someone else's C interpreter at the
moment (for a new language). So I have to enter C source for it to interpret
somehow, which is easiest as embedded string literals. Needless to say, the
editor won't offer editing support for code in strings.
Post by David Brown
Post by bartc
That fact is that if I upload any C code to pastebin or github now, they
won't insert separators in my numbers, even if the tool I use myself
does so (it doesn't).
Syntax highlighting of new features /is/ an issue - you are right there.
In particular, when adding a new language feature it is helpful if
existing popular editors do not mark it as a syntax error.
That's a real problem. So too when there's a bug in the editor's parser,
as happens a bit with XCode.
bartc
2017-05-12 14:21:33 UTC
Permalink
Raw Message
Post by David Brown
Post by bartc
You would hope however that every text viewer could show ASCII.
Do you know of any that can't?
I mention that because I've used displays that were upper case, so a..z,
{ and }, and some punctuation would be missing. A bit of a problem for C
source.

They've always managed "$" however.
--
bartc
David Brown
2017-05-12 15:06:19 UTC
Permalink
Raw Message
Post by bartc
Post by David Brown
Post by bartc
You would hope however that every text viewer could show ASCII.
Do you know of any that can't?
I mention that because I've used displays that were upper case, so a..z,
{ and }, and some punctuation would be missing. A bit of a problem for C
source.
From what century?

I have used displays that could not use colour syntax highlighting
because they were black and white - but I don't consider it a big
problem these days.
Post by bartc
They've always managed "$" however.
bartc
2017-05-12 15:36:43 UTC
Permalink
Raw Message
Post by David Brown
Post by bartc
Post by David Brown
Post by bartc
You would hope however that every text viewer could show ASCII.
Do you know of any that can't?
I mention that because I've used displays that were upper case, so a..z,
{ and }, and some punctuation would be missing. A bit of a problem for C
source.
From what century?
Twentieth. More recently than when C was created anyway. In 1976 I was
using ASR33s for example.

Ancient stuff but then people are always going on about some feature of
C being that way otherwise it wouldn't work on hardware that's been
obsolete for decades.
Post by David Brown
I have used displays that could not use colour syntax highlighting
because they were black and white - but I don't consider it a big
problem these days.
That must have been a binary black and white video board I guess; the
display itself was probably monochrome. (I used to watch snooker on my
9" green-screen NEC monitor and it was easy to see which ball was which.)
--
bartc
David Kleinecke
2017-05-12 18:58:39 UTC
Permalink
Raw Message
Post by David Brown
I believe you have got your Usenet sub-threads mixed up. The issue here
is David K's absurd idea that there are no editors that highlight
typedef names.
You are treating me as having far too much poser. All I
said was I didn't know of any.

That is your cue to make me better informed. I don't pretend
to know everything. All I knew about XCode was that it was an
Apple-oriented product. I still don't take Apple seriously.
David Brown
2017-05-14 15:03:18 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by David Brown
I believe you have got your Usenet sub-threads mixed up. The issue here
is David K's absurd idea that there are no editors that highlight
typedef names.
You are treating me as having far too much poser. All I
said was I didn't know of any.
Fair enough. I apologise for being unnecessarily rude.
Post by David Kleinecke
That is your cue to make me better informed.
I and others have already given suggestions of some very popular free
editors that highlight typedefs - I hope that is sufficient, since
discussions of the pros and cons of different editors and IDE's is
off-topic here. Suffice to say that most modern IDE's or editors that
parse C syntax will be able to highlight typedefs.
Post by David Kleinecke
I don't pretend
to know everything. All I knew about XCode was that it was an
Apple-oriented product. I still don't take Apple seriously.
XCode is, AFAIK, an IDE for Apple MacOS. I don't use Macs myself so I
can't tell you much about it.
bartc
2017-05-14 15:15:11 UTC
Permalink
Raw Message
Post by David Brown
Post by David Kleinecke
Post by David Brown
I believe you have got your Usenet sub-threads mixed up. The issue here
is David K's absurd idea that there are no editors that highlight
typedef names.
You are treating me as having far too much poser. All I
said was I didn't know of any.
Fair enough. I apologise for being unnecessarily rude.
Post by David Kleinecke
That is your cue to make me better informed.
I and others have already given suggestions of some very popular free
editors that highlight typedefs - I hope that is sufficient, since
discussions of the pros and cons of different editors and IDE's is
off-topic here. Suffice to say that most modern IDE's or editors that
parse C syntax will be able to highlight typedefs.
How do you get github to highlight typedefs?

Assuming it manages it, how will it get access to the nested include
file where the typedef is actually defined? Or to the compile-time
macros that specify whether something should be a typedef? Where does it
look to find the standard C headers? As these are not usually part of a
project.

The general problem is quite difficult I think, and involves doing a
full parse of source code as though it was being compiled. But it can
also be specific to a compiler.
--
bartc
David Brown
2017-05-14 21:25:54 UTC
Permalink
Raw Message
Post by bartc
Post by David Brown
Post by David Kleinecke
Post by David Brown
I believe you have got your Usenet sub-threads mixed up. The issue here
is David K's absurd idea that there are no editors that highlight
typedef names.
You are treating me as having far too much poser. All I
said was I didn't know of any.
Fair enough. I apologise for being unnecessarily rude.
Post by David Kleinecke
That is your cue to make me better informed.
I and others have already given suggestions of some very popular free
editors that highlight typedefs - I hope that is sufficient, since
discussions of the pros and cons of different editors and IDE's is
off-topic here. Suffice to say that most modern IDE's or editors that
parse C syntax will be able to highlight typedefs.
How do you get github to highlight typedefs?
I don't know - I haven't tried.
Post by bartc
Assuming it manages it, how will it get access to the nested include
file where the typedef is actually defined? Or to the compile-time
macros that specify whether something should be a typedef? Where does it
look to find the standard C headers? As these are not usually part of a
project.
If an editor, IDE, or other syntax highligher cannot get access to all
the headers involved, along with known pre-defined macros for the C
implementation, then at least some aspects of the syntax highlighting
are going to be limited.

But for editing source code, at least for serious work, it is rarely a
problem to have a decent IDE or editor that /can/ see all the include
files, and can be appropriately configured to match the compilation
environment. I can't tell you if /all/ such tools highlight typedefs -
but I know that many do, and that even without that one feature, the
syntax highlighting, online error indications, auto-completions, and
other tools can save a great deal of effort.
Post by bartc
The general problem is quite difficult I think, and involves doing a
full parse of source code as though it was being compiled. But it can
also be specific to a compiler.
Yes, it involves a good bit of work. It makes sense for a large
programmers' editor, but not for a simple highlighter.
Keith Thompson
2017-05-14 20:55:41 UTC
Permalink
Raw Message
David Brown <***@hesbynett.no> writes:
[...]
Post by David Brown
I and others have already given suggestions of some very popular free
editors that highlight typedefs - I hope that is sufficient, since
discussions of the pros and cons of different editors and IDE's is
off-topic here. Suffice to say that most modern IDE's or editors that
parse C syntax will be able to highlight typedefs.
I don't generally use syntax highlighting myself, but I tried several
editors that do it (gvim, emacs, jedit, gedit). When editing a
source file containing:

typedef int Integer;
Integer x = 42;
int n = 100;

emacs and gvim both highlight "Integer" and "int" in the same way --
and continue to do so if the typedef is commented out. jedit and
gedit don't highlight "Integer" at all. (It's entirely possible
there are some settings I don't know about that would affect this
behavior.)

My guess is that emacs and gvim use some kind of heuristic to guess that
"Integer" is probably a type name, rather than processing the typedef
declaration. Such a heuristic probably works well enough, given that
the consequences of guessing wrong are not terribly serious.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Richard Bos
2017-05-14 13:38:12 UTC
Permalink
Raw Message
Post by David Brown
Post by bartc
You can't decide whether or not to add a language feature based on the
capabilities of a handful of smart editors.
"Add a language feature"? How long has C had typedef? 40 years?
And if you are working as a programmer and don't have a decent editor,
it is /your/ fault.
Erm.

Sometimes it's your employer's fault.

We're not all so wealthy that we can afford to _choose_ our boss.

Richard
GOTHIER Nathan
2017-05-14 14:42:21 UTC
Permalink
Raw Message
On Sun, 14 May 2017 13:38:12 GMT
Post by Richard Bos
We're not all so wealthy that we can afford to _choose_ our boss.
Let me guess your boss bought your services at the slave bazaar. :o)

Anyway in my view, vi is a minimal decent editor to write code or documentation.
David Brown
2017-05-14 15:07:44 UTC
Permalink
Raw Message
Post by Richard Bos
Post by David Brown
Post by bartc
You can't decide whether or not to add a language feature based on the
capabilities of a handful of smart editors.
"Add a language feature"? How long has C had typedef? 40 years?
And if you are working as a programmer and don't have a decent editor,
it is /your/ fault.
Erm.
Sometimes it's your employer's fault.
We're not all so wealthy that we can afford to _choose_ our boss.
That is true. But most programmers would be able to say to their boss
"I would be more productive in my job, giving you more code and/or
higher quality in less time, if I were allowed to use a good editor.
These ones here are available for free". Most bosses are swayed by an
argument like that.

There will, of course, be some programmers whose boss is better suited
to some bad American comedy than to a managerial position. And there
will be some companies with such strict policies on what can be run that
it is a long and expensive business to "qualify" an editor for use.

So okay - /usually/ it is your fault!
Malcolm McLean
2017-05-14 15:12:06 UTC
Permalink
Raw Message
Post by David Brown
There will, of course, be some programmers whose boss is better suited
to some bad American comedy than to a managerial position. And there
will be some companies with such strict policies on what can be run that
it is a long and expensive business to "qualify" an editor for use.
So okay - /usually/ it is your fault!
Then when I was doing mainframe programming, the code physically
resided on the mainframe. I could have set something up to download
it, edit it locally, then upload it, but it would have been fiddly
to set up. So everyone in fact just edited source on the machine.
Which meant over a black and white console, in emacs or (shudder)
vi.
David Brown
2017-05-14 21:27:27 UTC
Permalink
Raw Message
Post by Malcolm McLean
Post by David Brown
There will, of course, be some programmers whose boss is better suited
to some bad American comedy than to a managerial position. And there
will be some companies with such strict policies on what can be run that
it is a long and expensive business to "qualify" an editor for use.
So okay - /usually/ it is your fault!
Then when I was doing mainframe programming, the code physically
resided on the mainframe. I could have set something up to download
it, edit it locally, then upload it, but it would have been fiddly
to set up. So everyone in fact just edited source on the machine.
Which meant over a black and white console, in emacs or (shudder)
vi.
When I were a lad, I did my debugging by listening to the changes in the
buzzing of the power supply on my ZX Spectrum. That does not make it a
relevant debugging strategy for a /professional/ programmer working /today/.
Ian Collins
2017-05-15 04:59:08 UTC
Permalink
Raw Message
Post by David Brown
Post by Malcolm McLean
Post by David Brown
There will, of course, be some programmers whose boss is better suited
to some bad American comedy than to a managerial position. And there
will be some companies with such strict policies on what can be run that
it is a long and expensive business to "qualify" an editor for use.
So okay - /usually/ it is your fault!
Then when I was doing mainframe programming, the code physically
resided on the mainframe. I could have set something up to download
it, edit it locally, then upload it, but it would have been fiddly
to set up. So everyone in fact just edited source on the machine.
Which meant over a black and white console, in emacs or (shudder)
vi.
When I were a lad, I did my debugging by listening to the changes in the
buzzing of the power supply on my ZX Spectrum. That does not make it a
relevant debugging strategy for a /professional/ programmer working /today/.
Unless someone pays you to write software for a Spectrum...
--
Ian
David Brown
2017-05-12 10:34:12 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by Keith Thompson
Not everyone uses highlighting text editors.
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
Even if it were true that there are few editors that highlight typedef
names (and it is not true), there are a great many other things that a
highlighting editor helps with. Typedef highlighting is only one of
many things.
David Kleinecke
2017-05-12 18:48:17 UTC
Permalink
Raw Message
Post by David Brown
Post by David Kleinecke
Post by Keith Thompson
Not everyone uses highlighting text editors.
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
Even if it were true that there are few editors that highlight typedef
names (and it is not true), there are a great many other things that a
highlighting editor helps with. Typedef highlighting is only one of
many things.
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.

I might make use of a highlighting of every identifier
that was not yet declared. But that would seem to imply
an editor setup where both the .c and .h were being
written at the same time.
Ian Collins
2017-05-12 19:41:48 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by David Brown
Even if it were true that there are few editors that highlight typedef
names (and it is not true), there are a great many other things that a
highlighting editor helps with. Typedef highlighting is only one of
many things.
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.
I might make use of a highlighting of every identifier
that was not yet declared. But that would seem to imply
an editor setup where both the .c and .h were being
written at the same time.
Most IDE based editors have some form of code assistance which uses
background compilation to do such things.
--
Ian
David Kleinecke
2017-05-13 00:38:21 UTC
Permalink
Raw Message
Post by Ian Collins
Post by David Kleinecke
Post by David Brown
Even if it were true that there are few editors that highlight typedef
names (and it is not true), there are a great many other things that a
highlighting editor helps with. Typedef highlighting is only one of
many things.
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.
I might make use of a highlighting of every identifier
that was not yet declared. But that would seem to imply
an editor setup where both the .c and .h were being
written at the same time.
Most IDE based editors have some form of code assistance which uses
background compilation to do such things.
The only IDE I have installed is Geany and it doesn't
highlight (unless it does and I have turned it off). I
haven't found an IDE that I like better than not using an
IDE.
GOTHIER Nathan
2017-05-12 23:23:10 UTC
Permalink
Raw Message
On Fri, 12 May 2017 11:48:17 -0700 (PDT)
Post by David Kleinecke
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.
I think the most helpful tool for C programmers is a good comprehension of the
language concepts. Any kind of calligraphic effect is only a distraction that
prevent programmers to adopt a good code design.

IMHO the "beauty" of the code doesn't lie in the shape of characters but
similarly to electronic circuits in the efficiency of the architecture.
Patrick.Schluter
2017-05-13 06:55:21 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Fri, 12 May 2017 11:48:17 -0700 (PDT)
Post by David Kleinecke
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.
I think the most helpful tool for C programmers is a good comprehension of the
language concepts. Any kind of calligraphic effect is only a distraction that
prevent programmers to adopt a good code design.
IMHO the "beauty" of the code doesn't lie in the shape of characters but
similarly to electronic circuits in the efficiency of the architecture.
Sorry, but what you say is not true in practice. The good presentation
of the code make the understanding of its working much, much easier.
If you want you can try to edit and correct your code next time in Comic
Sans font of size 15 (or any other proportional font) without coloring.
Also use tabs of a different size than the one used to write the source
and we will see how long it takes to find bugs or add features.
No, the presentation of the code is an important part of programming.
At work, I even introduced colorisation at the library level and
distinguishing between types, functions, deprecations etc... There were
more than 70 color combinations and it was great. With one view I could
see if a function was standard C, posix or Linux API or Solaris API. The
coloriser allowed to detect name clashes automagically.
This doesn't mean that one can not program without it, but that it's a
simple and not too obstrusive (if colours chosen decently) way to add
meta-data to the source code, saving a lot man, git grep and google
consultations.
ymmv
GOTHIER Nathan
2017-05-13 11:24:44 UTC
Permalink
Raw Message
On Sat, 13 May 2017 08:55:21 +0200
Post by Patrick.Schluter
Sorry, but what you say is not true in practice. The good presentation
of the code make the understanding of its working much, much easier.
If you want you can try to edit and correct your code next time in Comic
Sans font of size 15 (or any other proportional font) without coloring.
Also use tabs of a different size than the one used to write the source
and we will see how long it takes to find bugs or add features.
No, the presentation of the code is an important part of programming.
At work, I even introduced colorisation at the library level and
distinguishing between types, functions, deprecations etc... There were
more than 70 color combinations and it was great. With one view I could
see if a function was standard C, posix or Linux API or Solaris API. The
coloriser allowed to detect name clashes automagically.
This doesn't mean that one can not program without it, but that it's a
simple and not too obstrusive (if colours chosen decently) way to add
meta-data to the source code, saving a lot man, git grep and google
consultations.
ymmv
You should drop programming for painting at kindergarten. :o)
Tim Rentsch
2017-05-13 21:53:31 UTC
Permalink
Raw Message
Post by GOTHIER Nathan
On Fri, 12 May 2017 11:48:17 -0700 (PDT)
Post by David Kleinecke
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.
I think the most helpful tool for C programmers is a good
{} comprehension of the
language concepts. Any kind of calligraphic effect is only a
{} distraction that
prevent programmers to adopt a good code design.
IMHO the "beauty" of the code doesn't lie in the shape of
characters but similarly to electronic circuits in the efficiency
of the architecture.
Sorry, but what you say is not true in practice. The good
presentation of the code make the understanding of its working
much, much easier. [...elaboration...]
I believe what you are talking about, and what who you are
responding to is talking about, are two different things. For
example, for me to understand a piece of code it has to be
written for an English speaker rather than, say, German.
Similarly it should use a fixed-width font and suitable
indentation (or perhaps use typesetting to achieve the same
effects), some minimum level of white space (both horizontal
and vertical), and some other things. But these things are not
what makes code beautiful, in the sense that I mean the term.
The "beauty" of a piece of code has to do with how it achieves
its desired semantics. Presentation is also important, so that
the code can be comprehended, but that is orthogonal (or at
least largely orthogonal) to what I would characterize as
"beautiful" in programming.
David Brown
2017-05-14 15:10:40 UTC
Permalink
Raw Message
Post by David Kleinecke
Post by David Brown
Post by David Kleinecke
Post by Keith Thompson
Not everyone uses highlighting text editors.
A highlighting editor for C is essentially useless unless
it can recognize and highlight typedef names. That seems to
be something it would be possible to do. But I know of no
editor that does.
Even if it were true that there are few editors that highlight typedef
names (and it is not true), there are a great many other things that a
highlighting editor helps with. Typedef highlighting is only one of
many things.
The only other thing I find helpful is highlighting
comments. I admit to mostly using gedit as my editor.
I might make use of a highlighting of every identifier
that was not yet declared. But that would seem to imply
an editor setup where both the .c and .h were being
written at the same time.
To me, it is perfectly normal to be working on a .c and a .h file at the
same time. Indeed, I usually have quite a number of files open at once,
and for some files I have more than one editing window open at different
points in the same file.
Robert Wessel
2017-05-11 18:49:33 UTC
Permalink
Raw Message
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Probably because the world does not use digit group marks
consistently. Convention in India, for example, is to put a mark
before the rightmost group of three digits, but then another before
each additional *pair* of digits. IOW: "12,34,56,789". It also is
common to use groups of size other than three for other bases - groups
of two or four for hex, four for binary. So I suspect the simplest
thing was just to let them be used any way.
Patrick.Schluter
2017-05-11 19:57:21 UTC
Permalink
Raw Message
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Post by Robert Wessel
Post by Thiago Adams
What I find weird is that the position of ' is not verified.
Probably because the world does not use digit group marks
consistently. Convention in India, for example, is to put a mark
before the rightmost group of three digits, but then another before
each additional *pair* of digits. IOW: "12,34,56,789". It also is
common to use groups of size other than three for other bases - groups
of two or four for hex, four for binary. So I suspect the simplest
thing was just to let them be used any way.
In hex one would prefer to group by 4 or 2 for example.
Keith Thompson
2017-05-11 20:11:28 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Ada has done so since 1983, probably earlier. (The first preliminary
Ada standard was published in 1979; I don't remember whether it had
underscores as digit separators.) I don't know whether Ada was the
first language to do something like this, but I doubt it. It's fairly
clearly based on the use of underscores in identifiers, which is
certainly older than that.

The idea of a digit separator is obvious enough that there's no need to
assume it was copied without attribution from some specific language.

[...]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Patrick.Schluter
2017-05-11 20:21:30 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Patrick.Schluter
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Ada has done so since 1983, probably earlier. (The first preliminary
Ada standard was published in 1979; I don't remember whether it had
underscores as digit separators.) I don't know whether Ada was the
first language to do something like this, but I doubt it. It's fairly
clearly based on the use of underscores in identifiers, which is
certainly older than that.
The idea of a digit separator is obvious enough that there's no need to
assume it was copied without attribution from some specific language.
[...]
The thing is that quite some new features in C++ were inspired by D.
constexpr if being the most obvious one (that one is even provable to be
coming from D's "static if" because it was initially proposed by Walter
Bright and Andrei Alexandrescu for C++0x but rejected and then adopted
later under another name).
Thiago Adams
2017-05-11 20:56:52 UTC
Permalink
Raw Message
On Thursday, May 11, 2017 at 5:21:31 PM UTC-3, Patrick.Schluter wrote:
[...]
Post by Patrick.Schluter
The thing is that quite some new features in C++ were inspired by D.
constexpr if being the most obvious one (that one is even provable to be
coming from D's "static if" because it was initially proposed by Walter
Bright and Andrei Alexandrescu for C++0x but rejected and then adopted
later under another name).
I remember that.
The constexpr if is different from original static if.
I guess (not sure) that the difference is that constexpr must
be a valid code.
And the static if was "walk to the next closing } "

static if could be used for structs.

struct X
{
static if (size(x) == 1)
{
int i;
}
}

static if is similar of #if with compiler information.
But the #if can go anywhere.
David Brown
2017-05-12 10:42:14 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Keith Thompson
Post by Patrick.Schluter
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Ada has done so since 1983, probably earlier. (The first preliminary
Ada standard was published in 1979; I don't remember whether it had
underscores as digit separators.) I don't know whether Ada was the
first language to do something like this, but I doubt it. It's fairly
clearly based on the use of underscores in identifiers, which is
certainly older than that.
The idea of a digit separator is obvious enough that there's no need to
assume it was copied without attribution from some specific language.
[...]
The thing is that quite some new features in C++ were inspired by D.
constexpr if being the most obvious one (that one is even provable to be
coming from D's "static if" because it was initially proposed by Walter
Bright and Andrei Alexandrescu for C++0x but rejected and then adopted
later under another name).
Even in that case, there is no reason to claim that it "comes from D".
Static or compile-time conditionals are not a fantastic invention of D -
they are an obvious and natural extension of C++'s moves to doing more
work at compile time rather than run time. It's just C pre-processor
#if, modernised to C++. About the only D thing about it is that some D
experts found that feature useful in D, wanted it in C++, and happened
to be in the position to do something about it (unlike the millions of
other C++ programmers who have wanted the same feature for years despite
never having seen D).
Robert Wessel
2017-05-11 20:44:26 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Patrick.Schluter
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Ada has done so since 1983, probably earlier. (The first preliminary
Ada standard was published in 1979; I don't remember whether it had
underscores as digit separators.) I don't know whether Ada was the
first language to do something like this, but I doubt it. It's fairly
clearly based on the use of underscores in identifiers, which is
certainly older than that.
I think it dates to (at least) Algol 68, at least in the modes which
support larger character sets.
Ben Bacarisse
2017-05-11 22:13:24 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Patrick.Schluter
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Ada has done so since 1983, probably earlier. (The first preliminary
Ada standard was published in 1979; I don't remember whether it had
underscores as digit separators.)
I have an Ada Reference Manual (in book form) dated 1980. I think it is
the first but it certainly includes digit separators.

<snip>
--
Ben.
Scott Lurndal
2017-05-12 16:16:02 UTC
Permalink
Raw Message
Post by Patrick.Schluter
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Hey, another thing C++ copies from D without attribution (D uses _ to
group digits).
Using grouping characters is much older than D. Verilog, for example,
uses _ to group digits.
David Brown
2017-05-12 10:35:59 UTC
Permalink
Raw Message
Post by Robert Wessel
On Thu, 11 May 2017 05:07:17 -0700 (PDT), Thiago Adams
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
What I find weird is that the position of ' is not verified.
Probably because the world does not use digit group marks
consistently. Convention in India, for example, is to put a mark
before the rightmost group of three digits, but then another before
each additional *pair* of digits. IOW: "12,34,56,789". It also is
common to use groups of size other than three for other bases - groups
of two or four for hex, four for binary. So I suspect the simplest
thing was just to let them be used any way.
Also, you may well have other reasons for wanting to pick different
grouping, such as 2017'05'12 for writing a date as an integer.
Richard Heathfield
2017-05-12 10:41:29 UTC
Permalink
Raw Message
On 12/05/17 11:35, David Brown wrote:
<snip>
Post by David Brown
Also, you may well have other reasons for wanting to pick different
grouping, such as 2017'05'12 for writing a date as an integer.
Why not just write it as 2457886 ?
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
David Brown
2017-05-12 15:27:46 UTC
Permalink
Raw Message
Post by Ben Bacarisse
<snip>
Post by David Brown
Also, you may well have other reasons for wanting to pick different
grouping, such as 2017'05'12 for writing a date as an integer.
Why not just write it as 2457886 ?
I am afraid I can't figure that one out. You'll have to give me a hint.
Robert Wessel
2017-05-12 15:57:21 UTC
Permalink
Raw Message
On Fri, 12 May 2017 17:27:46 +0200, David Brown
Post by David Brown
Post by Ben Bacarisse
<snip>
Post by David Brown
Also, you may well have other reasons for wanting to pick different
grouping, such as 2017'05'12 for writing a date as an integer.
Why not just write it as 2457886 ?
I am afraid I can't figure that one out. You'll have to give me a hint.
It's today's Julian day number.
David Brown
2017-05-14 15:15:03 UTC
Permalink
Raw Message
Post by Robert Wessel
On Fri, 12 May 2017 17:27:46 +0200, David Brown
Post by David Brown
Post by Ben Bacarisse
<snip>
Post by David Brown
Also, you may well have other reasons for wanting to pick different
grouping, such as 2017'05'12 for writing a date as an integer.
Why not just write it as 2457886 ?
I am afraid I can't figure that one out. You'll have to give me a hint.
It's today's Julian day number.
I missed that one when testing against different calendars. And there
you have the reason why I would not write the date that way!
j***@gmail.com
2017-05-12 13:55:17 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by Thiago Adams
C++ 17, has now a new if.
[...]
Single-Quotation-Mark as a Digit Separator
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf
int i = 1'000'000;
Comma (US and, I think, UK), period (some parts of Europe), and space
have other meaning in C.
Post by Thiago Adams
What I find weird is that the position of ' is not verified.
Well, it's mostly decoration, kind of like syntactic sugar.
Post by Thiago Adams
"An integer literal is a sequence of digits that has no period or exponent part, with optional
separating single quotes that are ignored when determining its value"
There are contexts in which you might prefer other groupings

These might be useful for reference, from Wikipedia:

https://en.wikipedia.org/wiki/Integer_literal#Digit_separators

https://en.wikipedia.org/wiki/Decimal_mark#Digit_grouping

https://en.wikipedia.org/wiki/Indian_numbering_system#Use_of_separators

--
Joel Rees

Delusions of being a novelist:
http://reiisi.blogspot.com/p/novels-i-am-writing.html
Loading...