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
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
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.

Loading...