Wednesday, January 11, 2017

Digest for comp.lang.c++@googlegroups.com - 17 updates in 6 topics

ram@zedat.fu-berlin.de (Stefan Ram): Jan 11 09:28PM

>And at the end he added: "..and if you divide by zero then you would
>maybe throw an exception....". But I have since been thinking is this
>the way:
 
The interviewer must first get clear about what it
is that he wants from you.
 
Does he want you to /implement a specification/?
 
Then /he/ needs to give you the specificatin he wants
you to implement, and this specification will specify
the behavior for zero. In this case, your job is to
/implement/ this specification, not to second-guess it.
 
Does he want you to /write a specification/ for a function?
 
Then there must be something by which to tell which
specification is "better". Usually an average function
serves some purpose in an ecosystem of a program or
a library, and you might need to have to ask more
questions about this to find out what a good
specification for the behavior could be.
 
Of course, I'd say, the classical C style would be:
 
The average function
 
Synopsis
 
#include <interview.h>
double average( const double * a, size_t n );
 
Description
 
The average function computes the average of the n values in
the array pointed to by a. If n is 0, the behavior is undefined.
 
Returns
 
The average function returns the average of the n values in
the array pointed to by a. If n is 0, the behavior is undefined.
ram@zedat.fu-berlin.de (Stefan Ram): Jan 11 09:42PM

>the behavior is undefined.
 
The physicists call »undefined behavior« a "singularity".
 
The big bang (the time between 0 and some early time)
was a singularity.
 
That means we own our existence to undefined behavior.
 
Blessed are you, undefined behavior.
ram@zedat.fu-berlin.de (Stefan Ram): Jan 11 10:54PM

>double average( const double * a, size_t n );
>If n is 0, the behavior is undefined.
 
Because, what's usually better than
 
try { ave = average( a, n ); }
catch( average_of_zero_exception e ) { oops(); }
 
is
 
if( n == 0 )oops(); else ave = average( a, n )
 
.
David Brown <david.brown@hesbynett.no>: Jan 11 12:59AM +0100

On 11/01/17 00:22, Ben Bacarisse wrote:
> with the new syntax for destructuring a value (which might not be the
> return from any function). But if you don't mind putting them all into
> the concept of "returning multiple values" I will hold my tongue.
 
I consider returning multiple values, and using them, as part of the
same process. Without structured bindings, it is a bit inconvenient to
use tuples to return multiple values from functions - with structured
bindings, it is easier and thus a more useful technique. It would be
even easier if we could write "return [1, 2];" instead of "return
std::make_tuple(1, 2);", but we have to have something to look forward
to in C++20 :-)
 
It is true that returning tuples is not only useful with structured
bindings, and structured bindings are not only useful with functions
that return tuples. However, I expect they will often be used in
conjunction and considered together as the normal way to return and use
multiple values from a function.
 
 
> The phrase is fine in casual conversation, but I thought the post was
> slightly misleading as an instructional one about the technique.
 
I'll agree that technically it was inaccurate - C++17 adds support for a
new way to use the multiple values returned as a tuple, but not new ways
for the actual return.
 
 
> It supports returning a tuple. If you go this route, you will find
> almost no language unable to return multiple values. What then do we
> call Common Lisp's multiple return values?
 
I am not familiar enough with Lisp to comment on it. But in Python,
returning a tuple like this is used for multiple return values, and
often referred to as multiple return values - even though technically it
is only returning a single value of tuple type.
 
 
> Undoubtedly. It's a hugely useful feature. Languages like ML have had
> type inference and structure pattern matching (they tend to go together)
> for decades and I miss them when they're not there.
 
I gather pattern matching in C++ is not yet ready for the standards, but
people are working on it. The proposal for structured bindings suggests
pattern matching with structured bindings, but recommends against
including them until pattern matching in general is ready.
 
> (For completeness, in Python you can write x,y = f() to pull the tuple
> apart.)
 
Yes, that's what you usually write. I only wrote "x = f()" to emphasise
that the Pythonic idiom for returning multiple values is really
returning a single tuple, just like in C++.
"Chris M. Thomasson" <invalid@invalid.invalid>: Jan 11 02:50PM -0800

On 1/9/2017 11:02 PM, Alf P. Steinbach wrote:
 
> It's hard top come up with a good name for `exec` here, but I've landed
> on `result_for`, because that makes the calling code readable:
 
> `func_foo::result_for(i )`.
 
Agreed.
 
 
> C++11 added support that means the input structure can be specified
> inline, as in the call `func_foo::exec({1, 2, 3})`.
 
Indeed. FWIW, sometimes I like to create the "input" structure ahead of
time, especially if it has many "parameters". Another contrived reason
is the ability to reuse a similar "template like" input structure cast
over many calls to (::result_for(i)) in the same scope.
 
 
 
> cout << quotient << ',' << remainder << endl;
> }
> [/code]
 
This looks very nice, however, imvvho this seems like a bit of a
"different" language to me. I understand auto, but personally still like
a type name in the source code:
___________________________
auto i0 = 123.0;
auto i1 = 123.0f;
 
vs:
 
double i0 = 123.0;
float i1 = 123.0f;
___________________________
 
Ahh, perhaps I need to brush up on my modern C++ skills!
 
;^o
 
 
FWIW, here is a little example of where I might want to use the input
output binding type thing. Here is a function that can find cycles in
the Mandelbrot set. It uses a slow and fast iteration "pointer",
basically identical to finding cycles in linked lists.
 
Here is the crude code using the "free-function" input/output
encapsulation "thing":
_____________________________________________
#include <complex>
#include <cstdio>
 
 
typedef double ct_float;
typedef std::complex<ct_float> ct_complex;
 
 
bool
ct_complex_compare(
ct_complex const& c0,
ct_complex c1,
ct_float epsilon
) {
ct_complex d = c1 - c0;
return std::abs(d) < epsilon;
}
 
 
struct mbrot_detect_cycle
{
struct input
{
ct_complex c;
ct_complex z;
ct_float escape;
ct_float epsilon;
unsigned int imax;
};
 
struct output
{
ct_complex z;
unsigned int i;
bool cycle;
};
 
static output result_for(input const& in)
{
ct_complex slow = in.z;
ct_complex fast = in.z;
 
for (unsigned int i = 0; i < in.imax; ++i)
{
slow = slow*slow + in.c;
 
fast = fast*fast + in.c;
fast = fast*fast + in.c;
 
if (ct_complex_compare(slow, fast, in.epsilon))
{
return{ slow, i, true };
}
 
ct_float dis = std::abs(slow);
 
if (dis > in.escape)
{
return{ slow, i, false };
}
 
// uncomment following line for progress meter... ;^)
//if (! (i % 10000)) std::printf("i:%u\r", i);
}
 
return{ slow, in.imax, false };
}
};
 
 
 
int main()
{
{
mbrot_detect_cycle::input in = {
// fine grain epsilon takes many iterations
// for this point (-.75, 0):
{ -.75, 0 },
{ 0, 0 },
2,
.0001,
500000000
};
 
mbrot_detect_cycle::output out =
mbrot_detect_cycle::result_for(in);
 
if (out.cycle)
{
std::printf(
"cycle found for in.c:(%f, %f) "
"at out.i:(%u) iterations in.epsilon:(%f)\n",
in.c.real(), in.c.imag(), out.i, in.epsilon);
}
 
else
{
std::printf(
"** NO ** cycle was found for in.c:(%f, %f) "
"at out.i:(%u) iterations in.epsilon:(%f)\n",
in.c.real(), in.c.imag(), out.i, in.epsilon);
}
}
 
return 0;
}
_____________________________________________
 
 
FWIW, one can try using different points to test. FWIW, I get the
following output for this code:
_____________________________________________
cycle found for in.c:(-0.750000, 0.000000) at out.i:(4291771) iterations
in.epsilon:(0.000100)
_____________________________________________
JiiPee <no@notvalid.com>: Jan 11 06:17PM

In my interview the interviewer asked me to write a function to
calculate an average value/mean.
 
And at the end he added: "..and if you divide by zero then you would
maybe throw an exception....". But I have since been thinking is this
the way:
 
 
double average(array of values)
 
{}
 
Seems like Bjarne recommends not to use exceptions when dividing by zero
but other ways. What would be the best way for the function to report
about "dividing by zero" case? How would you do it?
 
 
I kind of agree with Bjarne here.... do you?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jan 11 08:00PM +0100

On 11.01.2017 19:17, JiiPee wrote:
> but other ways. What would be the best way for the function to report
> about "dividing by zero" case? How would you do it?
 
> I kind of agree with Bjarne here.... do you?
 
I think your question is really three different questions:
 
• How to report division by zero for floating point calculations.
Easy, that's what NaN is all about.
 
• How to report division by zero for integer calculations.
Crash.
 
• How to sensibly deal with an empty set of values for `average`.
More thorny, discussed below.
 
Consider a multiset S of N numbers. Its average is avg(S) = sum(S)/N.
Now we form the set T = S ⊎ {42}, with N+1 numbers. Its average is
avg(T) = sum(T)/(N+1) = (42 + N*avg(S))/(N+1). A nice update formula.
 
So what if we want that to work for the case N = 0, i.e. S = {}?
 
Well, then N*avg(S), i.e. N*avg({}), should better equal 0. And it is 0
no matter which number we choose for avg({}). Unfortunately 0*NaN yields
NaN, but the choice that avg({}) = 0 sounds OK to me.
 
Another possibility is to return NaN, or to return an empty `Optional`
like `boost::optional` or C++17 `std::optional`. Or one could throw an
exception. Or, one could document the function's contract as requiring a
non-empty set, and then crash/assert on contract violation.
 
I think the most practically useful behavior would be the 0 return,
documented as such.
 
But, this opinion could be subject to revision if someone makes a good
case for some other possibility! ;-)
 
 
Cheers!,
 
- Af
JiiPee <no@notvalid.com>: Jan 11 07:16PM

On 11/01/2017 19:00, Alf P. Steinbach wrote:
> I think the most practically useful behavior would be the 0 return,
> documented as such.
 
But average can also be 0, cant it? So we cannot return 0 (zero) ...
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jan 11 09:43PM

On 11/01/2017 21:42, Stefan Ram wrote:
> was a singularity.
 
> That means we own our existence to undefined behavior.
 
> Blessed are you, undefined behavior.
 
Word salad.
 
/Flibble
Wouter van Ooijen <wouter@voti.nl>: Jan 11 11:20PM +0100

> documented as such.
 
> But, this opinion could be subject to revision if someone makes a good
> case for some other possibility! ;-)
 
I might not agree with 'return 0', but your approach is IMO the only
sound approach: try to find out what makes the most sense for the user.
But alas, that might not be the same for all users...
 
My approach is often 'let the user decide', which might be done by an
extra lambda/std::function parameter, which gets called in the
divide-by-zero cause. The default could be []{ return 0; }, to match
your case.
 
For a faster run in the normal cases, but undefined behaviour in the
divide-by-zero case, the caller should have the option to specify []{}
to signify that nothing is to be done, but I don't yet see how that
could be done. (Some template magic will probably help.)
 
An exception-oriented user could specify []{ throw <something>; }
 
Wouter "Objects? No Thanks!" van Oijen
David Brown <david.brown@hesbynett.no>: Jan 11 12:28AM +0100

On 10/01/17 23:24, Richard wrote:
> may be a newer version: <https://isocpp.org/files/papers/N4047.pdf>.
> For earlier discussions of a module system, see the references in the
> above paper.
 
Thank you for the information. I am glad to be corrected here - the C++
world gets better when everyone is working together. I guess I am just
a little disappointed that there are no modules in C++17, and I felt it
was unhelpful to have two competing (as I saw it) module systems. But
it was unfair of me to suggest that this was anything other than
people's desire to make a good technical solution rather than a fast fix.
 
> I'm unaware of any attempt, experimental or otherwise, to support modules
> in gcc.
 
I presume they are waiting until a solution is finalised (rather than
having yet another experimental version).
legalize+jeeves@mail.xmission.com (Richard): Jan 11 12:46AM

[Please do not mail me a copy of your followup]
 
David Brown <david.brown@hesbynett.no> spake the secret code
 
>Thank you for the information. I am glad to be corrected here - the C++
>world gets better when everyone is working together.
 
You're welcome, and thanks for the non-hostile attitude that one
normally sees on usenet :).
 
>I guess I am just
>a little disappointed that there are no modules in C++17,
 
Yeah, I wanted it as well, but if no standards committee proposal
resulted from the clang experiments and there was no gcc
implementation, it doesn't surprise me that it was considered too
green for C++17. They are really cautious about introducing new stuff
into the standard that hasn't been well tested.
 
>and I felt it
>was unhelpful to have two competing (as I saw it) module systems.
 
I consider the standards proposal to be an evolution of the clang
system instead of a competing system. It is different because it
incorporates the lessons learned from the clang experiments.
 
>I presume they are waiting until a solution is finalised (rather than
>having yet another experimental version).
 
Lots of proposed stuff for C++11, C++14 and C++17 has been implemented
from working paper proposals and the working proposal from Gabriel Dos
Reis et al seems good enough to me to start a working implementation.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Ian Collins <ian-news@hotmail.com>: Jan 11 05:45PM +1300

On 01/11/17 10:43 AM, David Brown wrote:
> significantly better, that's fair enough - but not if it is just them
> trying to be "first" at something in the C++ world.
 
> Still, it's nice to see MSVC are catching up with C++14.
 
C++14 has been the compiler's default mode for a while now.
 
--
Ian
David Brown <david.brown@hesbynett.no>: Jan 11 09:12AM +0100

On 11/01/17 01:46, Richard wrote:
> implementation, it doesn't surprise me that it was considered too
> green for C++17. They are really cautious about introducing new stuff
> into the standard that hasn't been well tested.
 
Some things get in faster, but I suppose in this case if the module
system under test turns out to have subtle flaws, it could cause /real/
problems for the future.
 
 
> I consider the standards proposal to be an evolution of the clang
> system instead of a competing system. It is different because it
> incorporates the lessons learned from the clang experiments.
 
Fair enough.
 
 
> Lots of proposed stuff for C++11, C++14 and C++17 has been implemented
> from working paper proposals and the working proposal from Gabriel Dos
> Reis et al seems good enough to me to start a working implementation.
 
Maybe they just haven't got round to it yet - there is no shortage of
tasks for the gcc developers (or clang developers, or, I expect, MSVC
developers). But if MSVC implements this, and clang update their
implementation to the same working paper proposal, then I would expect
gcc to follow if the current proposal is considered solid enough. It's
good not to have too many highly experimental implementations of a
feature, but also good to have more implementations once the feature
nears stability.
scott@slp53.sl.home (Scott Lurndal): Jan 11 06:06PM

>that it's somewhere between an advanced precompiled header and a
>module. It's less than full-blown modules and it's more than a
>precompiled header.
 
I really don't see the advantage to this. I worked for most of
a decade with a language called SPRITE which had modules, and
pre-compiled headers (called a Module Interface Definition). One
big source file defining all the modules, the public and private
module interfaces, composite types and global variables.
 
For large projects (this was a mainframe operating system), there
was significant contention to edit the MID (somewhat alleviated by
the patch method used to edit - engineers would submit patches to
the MID Master file, which would be re-generated once a week or
thereabouts).
 
C++ was perfect at version 2.1, and has been going downhill
ever since.
Jeff-Relf.Me <@.>: Jan 11 04:02AM -0800

Ian Collins <ian-news@hotmail.com>: Jan 11 05:41PM +1300

> On Thursday, January 5, 2017 at 5:43:34 PM UTC-6, Lofty Goat wrote:
 
> Please don't swear here.
 
Tit.
 
> At this Minnesota workplace, no swearing and no jerks allowed
 
So why are you here?
 
> "Ultimately, it's about mutual respect."
 
So where's your respect for the citizens of the countries you
gratuitously insulted?
 
--
Ian
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: