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/ :-)
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
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
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.
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.
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.
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.
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.
Loading...