- for ... else blocks - 10 Updates
- Why do some people hate namespace prefixes? - 14 Updates
- iostream formatting of special numbers - 1 Update
Ben Bacarisse <ben.usenet@bsb.me.uk>: Apr 17 01:06AM +0100 > { > // The logical "else" part. > } That looks like the Python meaning, not the one RCH was suggesting. I think RCH's intent can be written as: bool loop_body_executed = false; for (INIT; COND; UPDATE, loop_body_executed = true) { // ... } if (!loop_body_executed) { // The logical "else" part. } -- Ben. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 17 04:45AM +0200 On 17.04.2019 02:06, Ben Bacarisse wrote: > if (!loop_body_executed) { > // The logical "else" part. > } Thanks. That seems to indicate that there are at least two about equally convincing but exactly opposite notions of what `else` should mean if it were introduced as an extension to `for`... --- Anyway I find your example interesting because it's easier to read, and therefore grok, than my example that, more ideally, constrains the scope for modification of the variable. And I think that's due to two reasons: • That your example is shorter, mainly because of formatting. • That C++, from its C heritage, supports the changing-variables style of coding, and does not so much support expression based coding. In some other contexts the shorter formatting tends to produce what in my eyes is a gray wall of compact code, so I'm wary of adopting it. It's nice for books and articles, though, where vertical space is a limited resource. But on the third and gripping hand I may be too old to change formatting preferences again... --- Going back even further historically, C's parent language BCPL had a construct that one can think of as "arithmetic blocks", like a curly braces compound statement that could return a value. And expressing your example with an imaginary such construct it's not significantly more to read, and then properly constrains the scope where the code can change or influence the value of the boolean: const bool loop_body_executed = BCPL_BLOCK { for (INIT; COND; UPDATE) { if( SOMETHING ) { return true; } } return false; }; if( not loop_body_executed ) { // The logical "else" part. } --- As it happens it's easy to define a macro like BCPL_BLOCK: #define BCPL_BLOCK ~[&]() ... where the `~` operator is defined as e.g. namespace lambda_support { using std::declval; template< class Func , class Enabled_ = decltype( declval<Func>()() ) inline auto operator~( Func const& f ) -> decltype(( f() )) { return f(); } } // namespace lambda_support One just needs a `using` statement for it. Hence the need for SFINAE to ensure that this definition only kicks in, that it's only found, when `~` is applied to something callable without arguments. It should probably be even more constrained than what I managed above. So, that notation is not hypothetical. It's also easy to provide bindings for the lambda, e.g. using the `%` operator. It would be (or was when I tried it out, some years ago, then named `$invoked_with` instead of BCPL_BLOCK) a rather ugly hack that didn't entirely prevent incorrect use, but if one could get language and/or standard library support then it could be safe, because the standard library is allowed to use magic. I'd prefer a core language prefix invocation operator. Cheers!, - Alf |
David Brown <david.brown@hesbynett.no>: Apr 17 09:32AM +0200 On 17/04/2019 04:45, Alf P. Steinbach wrote: > Thanks. That seems to indicate that there are at least two about equally > convincing but exactly opposite notions of what `else` should mean if it > were introduced as an extension to `for`... And that would indicate that neither is a good idea, and "for else" should be avoided. Both cases can be easily and clearly handled by a bool flag, which a good compiler can often eliminate entirely (and it's a cheap solution even if the compiler can't remove it). > • That your example is shorter, mainly because of formatting. > • That C++, from its C heritage, supports the changing-variables style > of coding, and does not so much support expression based coding. I think the principle of avoiding changing variables is good, but it can be taken too far. Many factors contribute to code clarity - obsessing over any one of them is likely to give you worse (i.e., less legible) code in the end. > ensure that this definition only kicks in, that it's only found, when > `~` is applied to something callable without arguments. It should > probably be even more constrained than what I managed above. You do like to come up with some convoluted code, don't you? I found that one interesting, however. Your next challenge is to use concepts to remove the "Enabled" bit. |
Bart <bc@freeuk.com>: Apr 17 11:38AM +0100 On 17/04/2019 08:32, David Brown wrote: >> Thanks. That seems to indicate that there are at least two about equally >> convincing but exactly opposite notions of what `else` should mean if it >> were introduced as an extension to `for`... Its use in Python is not hard to understand. Its use as described in the OP is harder (RCH's ideas for features always are). > should be avoided. Both cases can be easily and clearly handled by a > bool flag, which a good compiler can often eliminate entirely (and it's > a cheap solution even if the compiler can't remove it). The idea is to avoid the extra logic. Here's a typical use in one of my languages (real example): for sw to optionnames.len do if eqstring(name,optionnames[sw]) then do_option(sw,value) exit fi else println "Unknown option:",name stop 1 od This for a language at the level of C (I'm posting from that group). A higher level might just say 'sw in optionnames', but since many won't have eliminated for-loops completely, there is likely still to be a use for for-else. The alternative as you say is to use a flag: optionno:=0 for sw ... ... optionno:=sw ... od if optionno then do_option ... else println ... fi I must have written a thousand such loops; the for-else feature provides a welcome respite, as well as a self-contained solution in one statement. The flag version introduces a new variable that demands an extra, wider scope, something at odds with your preference for narrower block scopes. |
David Brown <david.brown@hesbynett.no>: Apr 17 02:05PM +0200 On 17/04/2019 12:38, Bart wrote: >>> convincing but exactly opposite notions of what `else` should mean if it >>> were introduced as an extension to `for`... > Its use in Python is not hard to understand. That is debatable. But I agree it is easier (and more useful) than Rick's suggestion. > println "Unknown option:",name > stop 1 > od bool found = false; int sw; for (sw = 0; sw < len; sw++) { if (strcmp(name, options[sw]) == 0) { found = true; break; } } if (found) { do_option(sw, value); } else { printf("Unknown option: %s\r\n", name); stop(1); } The "for else" construct is not necessary, and the bool flag solution will be just as efficient. Structuring the code as "try to find the match, then handle the result" is arguably neater (and by "arguably", I don't mean it is /definitely/ neater). It also makes it easier to refactor the code if you have a different way of searching, perhaps as a separate function. > fi > I must have written a thousand such loops; the for-else feature provides > a welcome respite, as well as a self-contained solution in one statement. A smaller and more compact solution could be nice - but that would, as you say, require a higher level language. > The flag version introduces a new variable that demands an extra, wider > scope, something at odds with your preference for narrower block scopes. I have a preference for narrower scopes, all else being equal. But if the data is needed over a wider range, then a wider scope is the answer. |
Bart <bc@freeuk.com>: Apr 17 01:57PM +0100 On 17/04/2019 13:05, David Brown wrote: >>>> were introduced as an extension to `for`... >> Its use in Python is not hard to understand. > That is debatable. The controversy is with the use of the 'else' keyword. The idea of having code executed only on normal loop termination, not so much. > } > The "for else" construct is not necessary, and the bool flag solution > will be just as efficient. So why not: if (found) { do_option(sw, value); } if (!found) { printf("Unknown option: %s\r\n", name); exit(1); } We don't really need 'if else' either. (I'm sure I didn't have that in Fortran years ago.) > A smaller and more compact solution could be nice - but that would, as > you say, require a higher level language. By higher level I mean something like: do_option(name in optionnames, value) 'in' would return 1..len or 0, so do_option would have to deal with a option code of 0, to keep it simple. Higher level code tends not to have so many explicit loops, but so long as for-loops /are/ still used, then an 'else' clause containing dedicated code for a normal termination rather than a break will still be useful. |
David Brown <david.brown@hesbynett.no>: Apr 17 03:36PM +0200 On 17/04/2019 14:57, Bart wrote: >> That is debatable. > The controversy is with the use of the 'else' keyword. The idea of > having code executed only on normal loop termination, not so much. It is the use of the "else" keyword that you said was not hard to understand in Python, and I said it was debatable how hard that is. The poster that first mentioned said that the "else" keyboard in Python "for" loops is more often a subject of confusion than a useful coding technique. Clearly I don't disagree that sometimes it is useful to execute different code when a loop is terminated early. > } > We don't really need 'if else' either. (I'm sure I didn't have that in > Fortran years ago.) Sometimes that is a preferable arrangement. But this is a straw man (whataboutism, if you prefer) - we have "if ... else ..." in C. A key difference is that "if ... else ..." is extremely useful, and extremely common in most imperative languages. A "for ... else ..." construct is only occasionally useful - as for all constructs, that usefulness must be weighed against the additional learning and the potential for confusion. For "if ... else ...", the balance is clearly on the "useful" side. For "for ... else ...", the balance would appear to be on the "confusing" side. (Before you bring in more whataboutisms, C already has constructs that are more often confusing than useful. There is no need to mention them or list them.) > do_option(name in optionnames, value) > 'in' would return 1..len or 0, so do_option would have to deal with a > option code of 0, to keep it simple. That is an odd construct - I would not expect to see it, or immediately know what was meant. I would rather expect something like: if (name in optionnames) { do_option(optionnames[name], value); } else { print "Unknown option" } or try { do_option(optionnames[name], value); } except on key_error { print "Unknown option" } (I am making up high-level syntax as I go here.) > as for-loops /are/ still used, then an 'else' clause containing > dedicated code for a normal termination rather than a break will still > be useful. I don't disagree that a "for ... else ..." clause could be useful. But I am not convinced that it is useful enough to overcome potential confusion - I think its use would be rare, and alternative simple and clear solutions are easily available. |
Bart <bc@freeuk.com>: Apr 17 03:05PM +0100 On 17/04/2019 13:05, David Brown wrote: > } > if (found) { > do_option(sw, value); Another point is that as written, 'sw' has to be known outside so cannot be local to the loop. (In my example, the code to be executed can be brought inside the loop body; sometimes it can't. But 'found' needs to be outside.) |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 17 04:15PM +0200 On 17.04.2019 14:57, Bart wrote: > do_option(name in optionnames, value) > 'in' would return 1..len or 0, so do_option would have to deal with a > option code of 0, to keep it simple. That places responsibility for dealing with an unknown option down in `do_option`, via an `if` or `switch` or something. I'd rather have that logic up front: if( const int id = 1 + my::index_of( name, optionnames ) ) { app::do_option( id, value ); } else { my::fail( ""s + __func__ + " - unknown option '" + name + "'" ); } > as for-loops /are/ still used, then an 'else' clause containing > dedicated code for a normal termination rather than a break will still > be useful. Consider also [](){ for( const& string item: optionnames ) { if( item == name ) { app::do_option( 1 + &item - &optionnames[0], value ); return; } } my::fail( ""s + __func__ + " - unknown option '" + name + "'" ); }(); `return` is a nice statement; here it returns to the point after the last semicolon. The perhaps currently cryptic JavaScript-like start and end of that code is a pattern that one might as well get used to. Cheers!, - Alf |
Bart <bc@freeuk.com>: Apr 17 03:16PM +0100 On 17/04/2019 14:36, David Brown wrote: >> option code of 0, to keep it simple. > That is an odd construct - I would not expect to see it, or immediately > know what was meant. Python has "in" but just returns True or False, which is not very helpful. My version returns the index where a occurs in b, although most useful for 1-based lists. I would rather expect something like: > if (name in optionnames) { > do_option(optionnames[name], value); You're doing a double lookup, one with "in", and one with [], which latter would require optionnames to be a dict. It gets messy. > I am not convinced that it is useful enough to overcome potential > confusion - I think its use would be rare, and alternative simple and > clear solutions are easily available. It's rare partly because languages don't have it! Although I already said it would have problems being added to C because of the ambiguity of 'else'. |
Juha Nieminen <nospam@thanks.invalid>: Apr 17 07:06AM As an avid armchair psychologist, it has always fascinated me why some people just hate namespace prefixes in C++, and go to great lengths to avoid them and will rabidly defend this practice, and oppose their use. No amoung of argumentation will convince them otherwise. I have literally never, ever, during my entire life (being programming as a hobby and as my payjob for over 20 years), seen somebody complain about having to write prefixes when they use some library (eg. some C library) that has a common prefix in all of its names. Not even if that prefix is separated from the rest of the name with an underscore. They don't mind having to write "prefix_name()", but for some peculiar reason they hate having to write "prefix::name()", and will get rid of having to do it. What's the difference? I don't think the explanation is in the characters themselves. I don't think '::' is somehow special compared to '_' that would elicit such a contrarian reaction. So what is it? I believe that it has to do with the fact that writing the prefix is *optional* in the case of C++ namespaces. Somehow the notion that it's optional makes them hate writing it. Whan it's *not* optional, as in it being part of the name itself (like is the case with many C libraries), it doesn't trigger the aversion reaction. However, just the knowledge that it's optional makes them hate having to write it. I bet that if they didn't know that writing namespace prefixes is optional, that you can bypass it with a `using` expression, they would not protest having to write it. |
leigh.v.johnston@googlemail.com: Apr 17 12:36AM -0700 On Wednesday, April 17, 2019 at 8:06:59 AM UTC+1, Juha Nieminen wrote: > I bet that if they didn't know that writing namespace prefixes is > optional, that you can bypass it with a `using` expression, they > would not protest having to write it. The answer to your question is irrationality. Alf is irrational. The cause could be a mild mental disorder. /Leigh |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 17 10:14AM +0200 >> would not protest having to write it. > The answer to your question is irrationality. Alf is irrational. The > cause could be a mild mental disorder. I gather that that's an effort to connect me to Juha's remarks, and as such it's dishonest. I and I guess others value many of your contributions to the group, but postings like those about sausages, the rabid religious discussions, the equally rabid swearing, the apparently seriousness of making a universal compiler, and occasional technical or ad hominem trolling such as now, detracts from that. Cheers!, - Alf |
leigh.v.johnston@googlemail.com: Apr 17 02:26AM -0700 On Wednesday, April 17, 2019 at 9:14:26 AM UTC+1, Alf P. Steinbach wrote: > equally rabid swearing, the apparently seriousness of making a universal > compiler, and occasional technical or ad hominem trolling such as now, > detracts from that. And when you add all those things (including the posts about sausages) together the result is still less egregious than your C++ coding style, Alf. /Leigh |
"Fred.Zwarts" <F.Zwarts@KVI.nl>: Apr 17 11:59AM +0200 "Juha Nieminen" schreef in bericht news:q96ja6$2l60$1@adenine.netfront.net... >I bet that if they didn't know that writing namespace prefixes is >optional, that you can bypass it with a `using` expression, they >would not protest having to write it. I won't say that I hate prefixes, sometimes I use them. But I prefer to use 'using', because it makes it easier for me to document where the names come from. I group the 'using' expressions in the same order as the #include lines. The block of #include lines is followed by a few blocks of 'using' declarations. One block for each #include. In this way it is easy to see why a particlular #include is needed and also from which #include the std::name originates. E.g.: #include <functional> #include <exception> #include <stdexcept> #include <string> #include <typeinfo> #include <vector> // Import some symbols from the include files. using std::ref; using std::reference_wrapper; using std::exception; using std::runtime_error; using std::string; using std::type_info; using std::vector; This shows immediately why <functional> is included. Another reason, in particular for names that are used very often, is that in complex expressions 'string' is easier to read than 'std::string', because it is easier to keep the expressions short. |
leigh.v.johnston@googlemail.com: Apr 17 03:08AM -0700 On Wednesday, April 17, 2019 at 10:59:27 AM UTC+1, F.Zwarts wrote: > Another reason, in particular for names that are used very often, is that in > complex expressions 'string' is easier to read than 'std::string', because > it is easier to keep the expressions short. This is a fallacious argument. "std::" is ONLY FIVE EXTRA CHARACTERS. Not using the prefix actually makes things harder not easier to grok as you can't tell at a glance what code is standard and what code is non-standard. /Leigh |
Ian Collins <ian-news@hotmail.com>: Apr 17 10:17PM +1200 On 17/04/2019 19:06, Juha Nieminen wrote: > I bet that if they didn't know that writing namespace prefixes is > optional, that you can bypass it with a `using` expression, they > would not protest having to write it. It depends... Writing std:: isn't particularly burdensome, but if the namespace or namespaces are long (such as those produced when using Google protpbuf), a using aids readability. -- Ian. |
"Fred.Zwarts" <F.Zwarts@KVI.nl>: Apr 17 12:41PM +0200 schreef in bericht news:a24842c2-63de-4ff9-8ad8-0766d1db0f87@googlegroups.com... >using the prefix actually makes things harder not easier to grok as you >can't tell at a glance what code is standard and what code is non-standard. >/Leigh If somebody missed the fact that string is defined in the std:: namespace, than he is probably a very inexperienced C++ programmer. For most C++ programmers, std:: adds nothing as a prefix to string in terms of readability. |
leigh.v.johnston@googlemail.com: Apr 17 03:54AM -0700 On Wednesday, April 17, 2019 at 11:41:58 AM UTC+1, F.Zwarts wrote: > than he is probably a very inexperienced C++ programmer. For most C++ > programmers, std:: adds nothing as a prefix to string in terms of > readability. Nonsense. These days with the idiom of using `auto` almost everywhere readability shouldn't be an issue and for the few places where we can't use `auto` it is more important than ever to fully qualify. /Leigh |
Bart <bc@freeuk.com>: Apr 17 12:02PM +0100 >> complex expressions 'string' is easier to read than 'std::string', because >> it is easier to keep the expressions short. > This is a fallacious argument. "std::" is ONLY FIVE EXTRA CHARACTERS. Not using the prefix actually makes things harder not easier to grok as you can't tell at a glance what code is standard and what code is non-standard. "std::" is nearly the same length as "string". So half of what you're trying to see is noise. And while "string" and "vector" are obviously distinct, "std::string" and "std::vector" are 45% identical by character, and 66% identical by token. Imagine if every noun in a piece of writing was prefixed with "eng::" to tell you it was standard English. It would be a joke. C++ has enough problems with readability without deliberately making it worse. |
leigh.v.johnston@googlemail.com: Apr 17 04:13AM -0700 On Wednesday, April 17, 2019 at 12:03:07 PM UTC+1, Bart wrote: > tell you it was standard English. It would be a joke. > C++ has enough problems with readability without deliberately making it > worse. In your opinion it is made worse; in my opinion and the opinion of others it is made worse by NOT having the prefix. /Leigh |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 17 02:19PM +0300 On 17.04.2019 10:06, Juha Nieminen wrote: > people just hate namespace prefixes in C++, and go to great lengths > to avoid them and will rabidly defend this practice, and oppose their > use. No amoung of argumentation will convince them otherwise. The namespaces are specifically designed in the way that they can be omitted if so desired. This is a feature, not a bug. If people are using a feature, there is nothing more to say, the feature is there to be used. Of course, as any other feature this one can be overused or misused as well. Obviously, omitting namespaces would be bad if it makes the code harder to read, instead of making it easier. Alas, the trouble is that what is harder and what is easier heavily depends on the person reading the code and what he/she is accustomed to. Somebody with a lot of experience and good memory might immediately recognize which namespace the names like 'inclusive_scan' or 'greg_month' come from and what they mean, whereas for others this may be a challenge. I guess it's the same as with the tab/space issue. Whatever you do you will never find a variant which would satisfy all people. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Apr 17 11:36AM On Wed, 2019-04-17, Juha Nieminen wrote: > people just hate namespace prefixes in C++, and go to great lengths > to avoid them and will rabidly defend this practice, and oppose their > use. No amoung of argumentation will convince them otherwise. I think c.l.c++ posters are atypical C++ users these days. In real life I've never met anyone who avoids prefixes that way. So in that sense it's a non-issue ... I try not to worry about it. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Apr 17 01:15PM On Wed, 2019-04-17, Fred.Zwarts wrote: >>can't tell at a glance what code is standard and what code is non-standard. >>/Leigh > If somebody missed the fact that string is defined in the std:: namespace, It's not, not necessarily. I may want to use the name "string" locally, and don't expect such a name to conflict with the standard library. Not to mention names like find(). > than he is probably a very inexperienced C++ programmer. For most C++ > programmers, std:: adds nothing as a prefix to string in terms of > readability. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
"Öö Tiib" <ootiib@hot.ee>: Apr 17 04:49AM -0700 > surprising to users if they both produced the same string after > formatting. It may not be a big deal for many users, but why > introduce unnecessary differences for no good reason? Reasoning depends on who are your customers. Some bigger players in that "standardization" game see benefits in unreasonable incompatibilities between implementations. Rest of participants don't want things to be as close to whatever is "implementation defined" as possible; they usually want things to be platform agnostic if possible. > fairly simple for the various forms of infinity, there's a bit more > complexity with NaNs. I'm less clear on what I want to do for > conversions from *text* format. It would be fine for me if >> did parse "infinity" as well (and then both "inf" and "infinity" on all platforms) but I would dislike if << would output "infinity" on some platforms and "inf" on others. If that can be turned off with some compile time switch then I would be happy with it. > happen if there are actual NaNs. I don't think it's unreasonable to > support formatting NaN payloads if the implementation does so for > normal floats. The goals and preferences of target audiences can be diametrically opposed there, but my impression is that majority likes portability. I have had experience that the programs that use NaNs as valid and meaningful values (in meanings of "not measured", "unknown" and/or "marked as noise") can have majority of data as NaNs. > This may ultimately need some configuration options, but I'd like to > be able to provide good defaults for most cases. If such NaN payload support can be turnable off compile time then I would be happy with it. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment