Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-02 Thread Jędrzej Nowacki
On Monday 01 of February 2016 15:16:33 you wrote:
> I am a great fanboy of algorithms and the STL, as should be clear by now
You are excused ;-) But seriously I do not think there is anything wrong about 
it, STL is a bit obscure, but fast and sometimes a code needs to be fast. 

> But I find the inlined lambda worse than an explicit loop. This is
> write-only  code, imo. Esp. since we can't (yet) use auto in the parameter
> list, but even then, I'd always give a lambda a name (cf. my mail in
> response to Christian).
Hmmm, In my opinion you do not like the most cool feature of lambdas :-) Each 
time I was forced to define a functor somewhere, in a completely different 
place then my code lived, I was sad and jealous of python lambda syntax. I 
value a code that can be read from top to down without major jumps. Naming 
lambdas causes my eyes to jump ("so for each element it calls a function 
FooBar... Ah which does that") and it also suggests that the lambda will be 
re-used ("ok, so now remember FooBar, as it will be used again..."). I would 
much prefer a simple inline comment before sequence of std::remove_if 
std::erase and others then named lambda.

Anyway I guess we are again hitting a "C++11 syntax that we were not used to" 
issue. So please do not create any policy about that, at least not for now. 

Btw. when you are taking an address of a function you force a compiler to de-
inline the function, I hope such de-optimization doesn't happen while naming 
lambdas.

> > For a bigger code we would actually require named functions. What do you 
> > think?
> 
> Named functions have two problems: a) that many compilers don't inline the 
> code. So at a minimum, you'd write a forwarding lambda, or the function
> would  be an auto variable holding a stateless lambda (the difference
> between the two is almost non-existent, anyway). And b) that they cannot
> carry state. Lambdas can.
Sorry I used wrong wording, by named function I meant, assigned lambda, a 
functor or a declared function.  In general a callable with a name, defined in 
a different place then used.

A propos inline'ing of functions, have you tried anonymous namespaces? That 
should help.  At least once I forced gcc to inline the code...

Cheers,
 Jędrek
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


[Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Marc Mutz
Hi,

We're seeing increasing use of lambdas in dev, and I'm a bit unhappy about the 
result.

E.g. (not picking on Anton here, I have done the same before):

 auto firstEqualsName = [](const QPair )
 {
  return qstricmp(name.constData(), header.first) == 0;
 };
 fields.erase(std::remove_if(fields.begin(), fields.end(),
 firstEqualsName),
  fields.end());

This is one way to write a unary predicate. But it hides the fact that the 
predicate depends on the parameter 'name' (an argument to the function this 
lambda is defined in).

With classical function objects, one would have written - at the call site:

 fields.erase(std::remove_if(fields.begin(), fields.end(),
 FirstEquals(name)),
  fields.end());

See the difference?

Now, we don't want to go back and write function objects for one-time use, but 
it would be nice to have this explicit syntax, would it not?

One way to have this with lambdas is to write a lambda that returns a lambda. 
We can do this, because auto return type deduction works for lambdas already 
in C++11, unlike for normal functions. With this, the above would become (hold 
tight):

  auto firstEquals = [](const auto ) {
return [](auto header) { return qstricmp(header.first, name) == 0; };
  }

where I used auto and dropped the const-& argument passing only for 
exposition, to get it onto a single line.

 fields.erase(std::remove_if(fields.begin(), fields.end(),
 firstEquals(name)),
  fields.end());

So, where to put the ugliness: on the definition of the lambda, or the call 
site? (Note that "if you use this lambda more than once, then X" is not a good 
answer, because you shouldn't use lambdas more than once. But with the lambda-
returning-lambda, you could actually reuse them:

// at global scope:

  auto firstEquals = [](const auto ) {
return [](auto header) { return qstricmp(header.first, name) == 0; };
  }

  // use in several functions - always the same type

Whereas without the outer lambda, each use would create a new type, and 
potentially duplicate code (same problem as QStringLiteral, and the same 
soultion, really: wrap them in a function, except for lambdas, because of the 
unnameable return type, we need to use another lambda instead of a classical 
function).

So, which one to use?

Thanks,
Marc

-- 
Marc Mutz  | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Jędrzej Nowacki
On Monday 01 of February 2016 11:08:54 Marc Mutz wrote:
> Hi,
> 
> We're seeing increasing use of lambdas in dev, and I'm a bit unhappy about
> the result.
> 
> E.g. (not picking on Anton here, I have done the same before):
> 
>  auto firstEqualsName = [](const QPair )
> {
>   return qstricmp(name.constData(), header.first) == 0;
>  };
>  fields.erase(std::remove_if(fields.begin(), fields.end(),
>  firstEqualsName),
>   fields.end());
> 
> This is one way to write a unary predicate. But it hides the fact that the
> predicate depends on the parameter 'name' (an argument to the function this
> lambda is defined in).
> 
> With classical function objects, one would have written - at the call site:
> 
>  fields.erase(std::remove_if(fields.begin(), fields.end(),
>  FirstEquals(name)),
>   fields.end());
> 
> See the difference?
> 
> Now, we don't want to go back and write function objects for one-time use,
> but it would be nice to have this explicit syntax, would it not?
> 
> One way to have this with lambdas is to write a lambda that returns a
> lambda. We can do this, because auto return type deduction works for
> lambdas already in C++11, unlike for normal functions. With this, the above
> would become (hold tight):
> 
>   auto firstEquals = [](const auto ) {
> return [](auto header) { return qstricmp(header.first, name) == 0;
> }; }
> 
> where I used auto and dropped the const-& argument passing only for
> exposition, to get it onto a single line.
> 
>  fields.erase(std::remove_if(fields.begin(), fields.end(),
>  firstEquals(name)),
>   fields.end());
> 
> So, where to put the ugliness: on the definition of the lambda, or the call
> site? (Note that "if you use this lambda more than once, then X" is not a
> good answer, because you shouldn't use lambdas more than once. But with the
> lambda- returning-lambda, you could actually reuse them:
> 
> // at global scope:
> 
>   auto firstEquals = [](const auto ) {
> return [](auto header) { return qstricmp(header.first, name) == 0;
> }; }
> 
>   // use in several functions - always the same type
> 
> Whereas without the outer lambda, each use would create a new type, and
> potentially duplicate code (same problem as QStringLiteral, and the same
> soultion, really: wrap them in a function, except for lambdas, because of
> the unnameable return type, we need to use another lambda instead of a
> classical function).
> 
> So, which one to use?
> 
> Thanks,
> Marc

Hi,

 I would just inline the lambda inside remove_if. That way "name" would be 
explicit in place in which it is used and you could avoid 2nd lambda. 

So it would look like that:

  fields.erase(std::remove_if(fields.begin(), 
  fields.end(),
  [](const QPair 
)
  {
  return qstricmp(name.constData(), 
header.first) == 0;
  }),
   fields.end());

// I hope that formating is still ok, and the code is not wrapped.

For a bigger code we would actually require named functions. What do you 
think?

Cheers,
 Jędrek
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Marc Mutz
On Monday 01 February 2016 10:23:34 Christian Kandeler wrote:
> On 02/01/2016 11:08 AM, Marc Mutz wrote:
> > We're seeing increasing use of lambdas in dev, and I'm a bit unhappy
> > about the result.
> > 
> > E.g. (not picking on Anton here, I have done the same before):
> >   auto firstEqualsName = [](const QPair
> >   ) {
> >   
> >return qstricmp(name.constData(), header.first) == 0;
> >   
> >   };
> >   fields.erase(std::remove_if(fields.begin(), fields.end(),
> >   
> >   firstEqualsName),
> >
> >fields.end());
> > 
> > This is one way to write a unary predicate. But it hides the fact that
> > the predicate depends on the parameter 'name' (an argument to the
> > function this lambda is defined in).
> > 
> > With classical function objects, one would have written - at the call 
site:
> >   fields.erase(std::remove_if(fields.begin(), fields.end(),
> >   
> >   FirstEquals(name)),
> >
> >fields.end());
> > 
> > See the difference?
> 
> Yes, but it is offset by another difference: As opposed to the function
> object, the lambda is defined right above the call site (or at least
> very close to it), so you can easily see that it captures an additional
> variable.
> I therefore think that this is not a problem.

The point of giving names to things (variable, functions, classes) in 
programming is so you don't need to look at the implementation all the time to 
see what it's doing. You only need to look when you want to see _how_ it's 
doing what it does.

So if you think that this is not a problem, then it's not a problem for you, 
either, if local variables are named only a, b, c, ... And I disagree.

Thanks,
Marc

-- 
Marc Mutz  | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Marc Mutz
On Monday 01 February 2016 10:18:25 Jędrzej Nowacki wrote:
> So it would look like that:
> 
>   fields.erase(std::remove_if(fields.begin(), 
>   fields.end(),
>   [](const QPair 
> )
>   {
>   return qstricmp(name.constData(), 
> header.first) == 0;
>   }),
>fields.end());
> 
> // I hope that formating is still ok, and the code is not wrapped.
> 

I am a great fanboy of algorithms and the STL, as should be clear by now :)

But I find the inlined lambda worse than an explicit loop. This is write-only 
code, imo. Esp. since we can't (yet) use auto in the parameter list, but even 
then, I'd always give a lambda a name (cf. my mail in response to Christian).

> For a bigger code we would actually require named functions. What do you 
> think?

Named functions have two problems: a) that many compilers don't inline the 
code. So at a minimum, you'd write a forwarding lambda, or the function would 
be an auto variable holding a stateless lambda (the difference between the two 
is almost non-existent, anyway). And b) that they cannot carry state. Lambdas 
can.

Thanks,
Marc

-- 
Marc Mutz  | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Christian Kandeler

On 02/01/2016 03:10 PM, Marc Mutz wrote:

The point of giving names to things (variable, functions, classes) in
programming is so you don't need to look at the implementation all the time to
see what it's doing. You only need to look when you want to see _how_ it's
doing what it does.

So if you think that this is not a problem, then it's not a problem for you,
either, if local variables are named only a, b, c, ...


Depending on the context, yes. For instance, I have never written this:
for (int thisIsACounterThatIsUsedForIteration = 0; 
thisIsACounterThatIsUsedForIteration < arrayLen; 
++thisIsACounterThatIsUsedForIteration) { ... }


Instead, I simply use the name "i". Inacceptable?


Christian
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Sergio Martins
On Monday, February 01, 2016 11:08:54 AM Marc Mutz wrote:
> Hi,
> 
> We're seeing increasing use of lambdas in dev, and I'm a bit unhappy about
> the result.
> 
> E.g. (not picking on Anton here, I have done the same before):
> 
>  auto firstEqualsName = [](const QPair )
> {
>   return qstricmp(name.constData(), header.first) == 0;
>  };
>  fields.erase(std::remove_if(fields.begin(), fields.end(),
>  firstEqualsName),
>   fields.end());
> 
> This is one way to write a unary predicate. But it hides the fact that the
> predicate depends on the parameter 'name' (an argument to the function this
> lambda is defined in).
> 
> With classical function objects, one would have written - at the call site:
> 
>  fields.erase(std::remove_if(fields.begin(), fields.end(),
>  FirstEquals(name)),
>   fields.end());
> 
> See the difference?
> 
> Now, we don't want to go back and write function objects for one-time use,
> but it would be nice to have this explicit syntax, would it not?
> 
> One way to have this with lambdas is to write a lambda that returns a
> lambda. We can do this, because auto return type deduction works for
> lambdas already in C++11, unlike for normal functions. With this, the above
> would become (hold tight):
> 
>   auto firstEquals = [](const auto ) {
> return [](auto header) { return qstricmp(header.first, name) == 0;
> }; }
> 
> where I used auto and dropped the const-& argument passing only for
> exposition, to get it onto a single line.
> 
>  fields.erase(std::remove_if(fields.begin(), fields.end(),
>  firstEquals(name)),
>   fields.end());
> 
> So, where to put the ugliness: on the definition of the lambda, or the call
> site? (Note that "if you use this lambda more than once, then X" is not a
> good answer, because you shouldn't use lambdas more than once. But with the
> lambda- returning-lambda, you could actually reuse them:
> 
> // at global scope:
> 
>   auto firstEquals = [](const auto ) {
> return [](auto header) { return qstricmp(header.first, name) == 0;
> }; }
> 
>   // use in several functions - always the same type
> 
> Whereas without the outer lambda, each use would create a new type, and
> potentially duplicate code (same problem as QStringLiteral, and the same
> soultion, really: wrap them in a function, except for lambdas, because of
> the unnameable return type, we need to use another lambda instead of a
> classical function).

I would write:

removeIfFirstEquals(fields, name): because:

1) I could read it in English instead of very verbose C++
2) I would not need to read the implementation

And for the implementation.. it doesn't matter, it's a named function, only 
does one small thing and does it good.

About the inlining, which compilers don't and does it make a difference ? A 
function call should negligible compared to erase + remove_if 


Regards,
-- 
Sérgio Martins | sergio.mart...@kdab.com | Software Engineer
Klarälvdalens Datakonsult AB, a KDAB Group company
Tel: Sweden (HQ) +46-563-540090, USA +1-866-777-KDAB(5322)
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread André Somers



Op 01/02/2016 om 15:16 schreef Marc Mutz:

On Monday 01 February 2016 10:18:25 Jędrzej Nowacki wrote:

So it would look like that:

   fields.erase(std::remove_if(fields.begin(),
   fields.end(),
   [](const QPair
)
   {
   return qstricmp(name.constData(),
header.first) == 0;
   }),
fields.end());

// I hope that formating is still ok, and the code is not wrapped.


I am a great fanboy of algorithms and the STL, as should be clear by now :)

But I find the inlined lambda worse than an explicit loop. This is write-only
code, imo. Esp. since we can't (yet) use auto in the parameter list, but even
then, I'd always give a lambda a name (cf. my mail in response to Christian).
While I applaud the naming of things, especiallly things non-trivial, I 
don't agree that an inlined lambda equates to write-only code. It can 
be, but doesn't need to be. The lambda-to-return a lambda looks more 
write-only than an inlined lambda does, IMHO.


While self-documenting code is great, I don't think it should come at 
the price of outlandish constructs like lambdas-returning-lambdas. It 
cleans up the code at the place you call the code, I give you that, but 
it makes the lambda definition itself too complicated. I prefer a 
comment if you think that documenting what is captured at the call site 
is needed.


 auto firstEqualsName = [](const QPair )
 {
  return qstricmp(name.constData(), header.first) == 0;
 };
 fields.erase(std::remove_if(fields.begin(), fields.end(),
 firstEqualsName /*captures */),
  fields.end());


Though for this particular construct, I certainly prefer a special 
function. The erase + remove_if, both using the same end iterator always 
annoys me.  So something like:


removeWhereFirstEquals(container c, const QByteArray& name);

André

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Kevin Kofler
Marc Mutz wrote:
> But I find the inlined lambda worse than an explicit loop. This is
> write-only code, imo. Esp. since we can't (yet) use auto in the parameter
> list, but even then, I'd always give a lambda a name (cf. my mail in
> response to Christian).

But writing it inline and without a name is the whole point of a lambda. If 
you're giving it a name anyway, you may as well declare a named functor 
class.

> Named functions have two problems: a) that many compilers don't inline the
> code. So at a minimum, you'd write a forwarding lambda, or the function
> would be an auto variable holding a stateless lambda (the difference
> between the two is almost non-existent, anyway). And b) that they cannot
> carry state. Lambdas can.

Named functor classes can, too.

And I actually like Sergio Martins's solution best: Write a 
removeIfFirstEquals(fields, name) wrapper that hides the lambda entirely. 
There, you can also inline the lambda because the name of the containing 
function (removeIfFirstEquals) makes it very clear what the lambda does. And 
the calling code does not have to care how the "if first equals" test is 
actually implemented.

Kevin Kofler

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Marc Mutz
On Monday 01 February 2016 14:16:57 Christian Kandeler wrote:
> On 02/01/2016 03:10 PM, Marc Mutz wrote:
> > The point of giving names to things (variable, functions, classes) in
> > programming is so you don't need to look at the implementation all the
> > time to see what it's doing. You only need to look when you want to see
> > _how_ it's doing what it does.
> > 
> > So if you think that this is not a problem, then it's not a problem for
> > you, either, if local variables are named only a, b, c, ...
> 
> Depending on the context, yes. For instance, I have never written this:
> for (int thisIsACounterThatIsUsedForIteration = 0;
> thisIsACounterThatIsUsedForIteration < arrayLen;
> ++thisIsACounterThatIsUsedForIteration) { ... }
> 
> Instead, I simply use the name "i". Inacceptable?

No, perfectly ok. But only because by unwrit convention indexed for-loops use 
'i', 'j', ... as the index variable, and iterator-based for-loops use 'it' as 
the iterator variable. As soon as you name an iterator 'i', say, it ceases to 
be acceptable.

-- 
Marc Mutz  | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Marc Mutz
On Monday 01 February 2016 17:06:51 Thiago Macieira wrote:
> On Monday 01 February 2016 11:08:54 Marc Mutz wrote:
> > One way to have this with lambdas is to write a lambda that returns a
> > lambda.  We can do this, because auto return type deduction works for
> > lambdas already in C++11, unlike for normal functions. With this, the
> > above
> >
> > would become (hold tight):
> > 
> >   auto firstEquals = [](const auto ) {
> 
> Does parameter auto detection work in C++11?

No, but you snipped the part of the mail where I explained that I used auto 
only to fit it to a single line.

-- 
Marc Mutz  | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Marc Mutz
On Monday 01 February 2016 13:34:05 Sergio Martins wrote:
> I would write:
> 
> removeIfFirstEquals(fields, name): because:
> 
> 1) I could read it in English instead of very verbose C++
> 2) I would not need to read the implementation

I tend to agree, but it only shifts the issue down one level of abstraction. 
And removeIfFirstEquals() isn't exactly clear, either. 
fields.removeIfFirstEquals(name) would be. Maybe when C++ lifts the distinction 
between a.f(b) and f(a, b)...

It also doesn't help when you need to reuse the lambda, e.g. when sorting a 
range by some predicate and then merging the range into an existing one.

> And for the implementation.. it doesn't matter, it's a named function,
> only  does one small thing and does it good.
> 
> About the inlining, which compilers don't and does it make a difference ?

Almost none do, unless they use/you switch on whole-program-optimisation.

> A  function call should negligible compared to erase + remove_if

It's not just a function call, it's a function call though a function pointer. 
Costs like a virtual function call and turns C++ std::sort into C's qsort. 
http://stackoverflow.com/questions/4708105/performance-of-qsort-vs-stdsort

Thanks,
Marc

-- 
Marc Mutz  | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Christian Kandeler

On 02/01/2016 11:08 AM, Marc Mutz wrote:

We're seeing increasing use of lambdas in dev, and I'm a bit unhappy about the
result.

E.g. (not picking on Anton here, I have done the same before):

  auto firstEqualsName = [](const QPair )
  {
   return qstricmp(name.constData(), header.first) == 0;
  };
  fields.erase(std::remove_if(fields.begin(), fields.end(),
  firstEqualsName),
   fields.end());

This is one way to write a unary predicate. But it hides the fact that the
predicate depends on the parameter 'name' (an argument to the function this
lambda is defined in).

With classical function objects, one would have written - at the call site:

  fields.erase(std::remove_if(fields.begin(), fields.end(),
  FirstEquals(name)),
   fields.end());

See the difference?


Yes, but it is offset by another difference: As opposed to the function 
object, the lambda is defined right above the call site (or at least 
very close to it), so you can easily see that it captures an additional 
variable.

I therefore think that this is not a problem.


Christian
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: lambda or lambda return from lambda?

2016-02-01 Thread Thiago Macieira
On Monday 01 February 2016 11:08:54 Marc Mutz wrote:
> One way to have this with lambdas is to write a lambda that returns a
> lambda.  We can do this, because auto return type deduction works for
> lambdas already in C++11, unlike for normal functions. With this, the above
> would become (hold tight):
> 
>   auto firstEquals = [](const auto ) {

Does parameter auto detection work in C++11?
-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development