Re: Anonymous functions: replace bind with lambdas

2016-08-28 Thread Guillaume Munch

Le 05/07/2016 à 20:39, Georg Baum a écrit :

Guillaume Munch wrote:


I have split the patch in two for you, and already committed the part
that does not introduce lambda expressions. Attached is the remainder of
the patch that replaces all remaining std::bind with lambda expressions.


Thanks. I am currently swamped with work, and this deserves a thorough look
so please be patient for a few days for my answer.




Hi Georg,

Here's the latest version of the patch. In this version I have decided
to follow the rule of doing capture by copy unless it is clear that the
reference will still be valid. Safety is well worth the cost. (And it
makes proof-reading simpler :)

In addition you will see that there is a "FIXME" comment for Windows and
I would gladly use your help with this one.

Thanks!

Guillaume

>From 14fa7667503cf95d1285bc474a7e877ebb3cc8d9 Mon Sep 17 00:00:00 2001
From: Guillaume Munch 
Date: Wed, 29 Jun 2016 11:40:28 +0100
Subject: [PATCH] Remove support/functional.h and support/bind.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace std::bind() with lambdas. This provides a much more readable code.

> It would help me if you could explain this new syntax. [...]
>
>> -theApp()->registerSocketCallback(fd,
>> -bind(::read_ready, this));
>> +theApp()->registerSocketCallback(fd, [this]() { read_ready(); });
>

In C++11, the syntax [X](Y){Z} is called a “lambda expression” and
denotes an anonymous function.

The (Y) is the list of arguments, with which you are already familiar in
function declarations, e.g. (std::string const & str). The {Z} is what
you would write in the body of such function (including the return
statement). It goes without saying that in the end, this is much
more readable and expressive than creating anonymous functions with
std::bind.

The power of the lambda expressions comes from the [X] parameter. Inside
Z, you can refer and access to any variable that you can already access
and refer to in the scope in which you write the lambda expression. For
instance, I wrote above "read_ready();" because I am essentially in the
scope of a member function of LyXComm, and therefore I can refer to (and
omit) "this->".

Now, the expression {Z} can be evaluated much later, and therefore all
the local variables it refers to may already have been destroyed.
Therefore we need the parameter [X] to indicate how the free variables
appearing in {Z} but not in (Y) are stored when creating the anonymous
function ("captured", in C++-speak). They are either stored by copying
or stored by reference. [X] is a list of variables possibly prefixed by
&, denoting a reference. For instance [x,,z] means that x and z are
copied and stored with the anonymous function on creation, whereas y is
stored as a reference to the original object.

In the example above, I refer (implicitly) to "this" and therefore I
must indicate that this (the pointer) is to be copied.

There are two shorthand syntaxes for [X]: [=,...] and [&,...]. =
indicates that all remaining free variables must be copied. & indicates
that all remaining variables must be stored by reference. (In both cases
the this pointer will be copied, not stored by reference.)

>>
>> +	auto compile = [=](std::string const & s) {
>> +		return clone->doExport(s, true);
>> +	};
>> +	return runAndDestroy(compile, orig, clone, format);

In the above example, the function "compile" calls clone->doExport where
"clone" is a copy of to the original pointer "clone", and where the
first argument is passed to it later by runAndDestroy.

The "auto" keyword asks to the compiler to deduce the type of the
function automatically, because the type of "compile" is too complicated
to write down. Note that it is still type-checked at compile-type (in
this case, the type is used to create an instance of the runAndDestroy
function template, and if compile was not an appropriate function, then
an error would occur at template instantiation. But one could also have
made the type explicit as std::function).
---
 src/Buffer.cpp |   8 +--
 src/Server.cpp |   6 +-
 src/ServerSocket.cpp   |  13 ++---
 src/frontends/qt4/GuiAlert.cpp |  58 ---
 src/frontends/qt4/GuiView.cpp  |  34 +++
 src/frontends/qt4/GuiWorkArea.cpp  |   8 +--
 src/frontends/qt4/InGuiThread.h| 114 ++---
 src/graphics/GraphicsCacheItem.cpp |   5 +-
 src/graphics/GraphicsConverter.cpp |   3 +-
 src/graphics/GraphicsLoader.cpp|   6 +-
 src/graphics/PreviewImage.cpp  |   4 +-
 src/graphics/PreviewLoader.cpp |   5 +-
 src/insets/InsetExternal.cpp   |   3 +-
 src/insets/InsetInclude.cpp|   6 +-
 src/insets/InsetText.cpp   |   6 +-
 src/insets/RenderGraphic.cpp   |   6 +-
 src/insets/RenderPreview.cpp   |   8 +--
 

Re: Anonymous functions: replace bind with lambdas

2016-07-09 Thread Guillaume Munch

Le 06/07/2016 22:37, Stephan Witt a écrit :

Am 05.07.2016 um 21:39 schrieb Georg Baum :

Thanks. I am currently swamped with work, and this deserves a thorough look
so please be patient for a few days for my answer.


Sure



I’m not familiar with lambda expressions too.

But I can tell you it compiles and runs on Mac with your patch applied
(against c6ce76c2fbe88c7882935d6c1bf44a6247943b97 with one hunk manually
applied).



Thanks for the test.




Re: Anonymous functions: replace bind with lambdas

2016-07-06 Thread Stephan Witt
Am 05.07.2016 um 21:39 schrieb Georg Baum :
> 
> Guillaume Munch wrote:
> 
>> I have split the patch in two for you, and already committed the part
>> that does not introduce lambda expressions. Attached is the remainder of
>> the patch that replaces all remaining std::bind with lambda expressions.
> 
> Thanks. I am currently swamped with work, and this deserves a thorough look 
> so please be patient for a few days for my answer.

I’m not familiar with lambda expressions too.

But I can tell you it compiles and runs on Mac with your patch applied
(against c6ce76c2fbe88c7882935d6c1bf44a6247943b97 with one hunk manually
applied).

Stephan

Re: Anonymous functions: replace bind with lambdas

2016-07-06 Thread Richard Heck

On 07/03/2016 05:36 PM, Guillaume Munch wrote:

Le 03/07/2016 20:52, Richard Heck a écrit :



One might wonder in such cases why things are being copied or passed
by reference, for example.


Unfortunately, while producing equivalent code is easy (or so it seems
so far), fully understanding the old code is hard. For instance, I trust
the old code that references are still valid when the callback is called.


Fair enough.

Richard



Re: Anonymous functions: replace bind with lambdas

2016-07-05 Thread Georg Baum
Guillaume Munch wrote:

> I have split the patch in two for you, and already committed the part
> that does not introduce lambda expressions. Attached is the remainder of
> the patch that replaces all remaining std::bind with lambda expressions.

Thanks. I am currently swamped with work, and this deserves a thorough look 
so please be patient for a few days for my answer.


Georg




Re: Anonymous functions: replace bind with lambdas

2016-07-03 Thread Guillaume Munch

Le 03/07/2016 20:52, Richard Heck a écrit :


My own view is that our code is undercommented---and I know I'm as bad
about this as anyone. That said, I often add comments to code I have to read
to fix various bugs, if only for my own benefit later.


I agree. I noticed myself doing that as well sometimes.



One might wonder in such cases why things are being copied or passed
by reference, for example.


Unfortunately, while producing equivalent code is easy (or so it seems
so far), fully understanding the old code is hard. For instance, I trust
the old code that references are still valid when the callback is called.

Actually, in some cases such as GuiAlert, where the call happens in a
different thread's temporality, the safety benefit of storing by copy
would (barring a better understanding of the assumptions that I do not
have) far outweigh the cost of copying the strings. I might even change
the code in this case for that reason.

So while I agree that comments regarding the old code would help, I
cannot make up this missing information.


No doubt the std::bind versions are write-only, but that only illustrates
my point: Our code is undercommented. In this case, for example:

@@ -741,7 +740,9 @@ void PreviewLoader::Impl::startLoading(bool wait)
  // Initiate the conversion from LaTeX to bitmap images files.
  ForkedCall::SignalTypePtr
  convert_ptr(new ForkedCall::SignalType);
-convert_ptr->connect(bind(::finishedGenerating, this, _1, _2));
+convert_ptr->connect([this](pid_t p, int retval) {
+finishedGenerating(p, retval);
+});

  ForkedCall call(buffer_.filePath());
  int ret = call.startScript(command, convert_ptr);

I'm not sure that the original author's decision not to add a comment is
a reason we shouldn't add one.


Do you mean a comment explaining the purpose of the code? Unfortunately
I cannot invent this information. Do you mean a comment describing the
anonymous function? Then adding the types and the names of the
arguments, which I had to look up, can already count as added comments.



I don't have a problem with the patch's being committed. But it's worth
remembering that most of us are amateurs. We don't all keep up with the
latest developments in compiler technology. As a result, discussions
about ways to make our codebase accessible to amateurs aren't at all
uncommon. I knew almost no C++ when I started working on LyX. The
way I learned, and especially the way I learned STL, was by doing.


Keeping the code accessible is something I have in mind. I believe that
my recent modifications involving C++11 features let us write simpler
and safer code.

(Now, for the cultural minute, I would really not call lambda
expressions the "latest development in compiler technology" given that
the lambda calculus is older than computer science, and its efficient
compilation older than C++.)

On a related matter, I have been thinking hard about how to take
advantage of the new move semantics while remaining simple (one issue
being that calling std::move can misleadingly incur a copy). I will
probably write another message about this soon, since I currently have
code the relies on it.



What was the issue with gcc 4.6?


A segfault, that I have since been unable to reproduce, but which I
could not make sense of despite having a backtrace.

Guillaume



Re: Anonymous functions: replace bind with lambdas

2016-07-03 Thread Richard Heck
On 07/03/2016 02:21 PM, Guillaume Munch wrote:
> Le 27/06/2016 23:15, Richard Heck a écrit :
>> On 06/27/2016 04:14 PM, Georg Baum wrote:
>>> You mean std::bind, or did I miss any remaining boost::bind?
>
> I just removed some leftover boost::function (not boost::bind).
>
>>> For me personally the patch is too big to proof-read it. I'd prefer to
>>> change simple things like
>>>
>>> -   BufferStorage::iterator it = bstore.begin();
>>> -   BufferStorage::iterator end = bstore.end();
>>> -   for (; it != end; ++it) {
>>> -   Buffer * buf = *it;
>>> +   for(Buffer * buf : bstore)
>>>
>>> which are not related to removal of std::bind first.
>>
>> Yes, that's a good idea.
>
>
> I have split the patch in two for you, and already committed the part
> that does not introduce lambda expressions. Attached is the remainder of
> the patch that replaces all remaining std::bind with lambda expressions.
>
>
>>
>>> Apart from that I am not too familiar with lambdas yet, so for me
>>> personally
>>> the new code is more difficult to read than the old one ATM, and I am
>>> probably not the only one. Your explanation to Richard is nice, but
>>> it will
>>> soon be buried in email archives, and people reading LyX sources do
>>> not see
>>> it.
>>>
>>> I am not opposed to using lambdas (I hope I can learn soemthing from
>>> you
>>> here), but I believe that our developer documentation should contain
>>> a short
>>> motivation why they are used in LyX (you basically explained already to
>>> Richard how they make code more readable), and a pointer to a more
>>> detailed
>>> introduction to lambdas. Then it should also be possible for novices
>>> or old-
>>> timers like me to understand the new hot stuff.
>>
>> It wouldn't hurt to put some comments in the code, too.
>>
>
> I am happy to explain my code to anybody who asks. However, I am not
> going to introduce a motivation for lambda expressions in the developer
> manual nor add links to introductions. The old code was already using
> anonymous functions; that lambda expressions is better for anonymous
> functions is obvious to anybody familiar with lambda expressions; and
> the documentation is not meant to be a tutorial for ISO C++.

My own view is that our code is undercommented---and I know I'm as bad
about this as anyone. That said, I often add comments to code I have to read
to fix various bugs, if only for my own benefit later.

You're right that it's clear enough what the intent is in many cases.
But I don't
think that's always true, and it wastes more time to decode something
than it
would take to comment it. Generally, cases like:
[this]() { someFunction(); }
are obviously easy to read. It's more complicated when there are various
arguments. One might wonder in such cases why things are being copied
or passed by reference, for example.

> Neither am I going to add comments to the code affected by the patch,
> because nobody felt like requiring such comments for the old code.
> Whereas the std::bind version can be hard to read for anybody, the new
> code is self-explanatory for anybody familiar with lambda expressions,
> and comments are again not meant to explain the language. 

No doubt the std::bind versions are write-only, but that only illustrates
my point: Our code is undercommented. In this case, for example:

@@ -741,7 +740,9 @@ void PreviewLoader::Impl::startLoading(bool wait)
 // Initiate the conversion from LaTeX to bitmap images files.
 ForkedCall::SignalTypePtr
 convert_ptr(new ForkedCall::SignalType);
-convert_ptr->connect(bind(::finishedGenerating, this, _1, _2));
+convert_ptr->connect([this](pid_t p, int retval) {
+finishedGenerating(p, retval);
+});
 
 ForkedCall call(buffer_.filePath());
 int ret = call.startScript(command, convert_ptr);

I'm not sure that the original author's decision not to add a comment is
a reason we shouldn't add one.

> If other developers are not familiar with lambda expressions yet, then
> it is appropriate to wait before committing. Given that I do not know
> the source of my issue with gcc 4.6, it is appropriate to wait that
> support for gcc 4.6 is dropped (probably about a year from now).

I don't have a problem with the patch's being committed. But it's worth
remembering that most of us are amateurs. We don't all keep up with the
latest developments in compiler technology. As a result, discussions
about ways to make our codebase accessible to amateurs aren't at all
uncommon. I knew almost no C++ when I started working on LyX. The
way I learned, and especially the way I learned STL, was by doing.

What was the issue with gcc 4.6?

Richard



Re: Anonymous functions: replace bind with lambdas

2016-07-03 Thread Guillaume Munch

Le 27/06/2016 23:15, Richard Heck a écrit :

On 06/27/2016 04:14 PM, Georg Baum wrote:

You mean std::bind, or did I miss any remaining boost::bind?


I just removed some leftover boost::function (not boost::bind).


For me personally the patch is too big to proof-read it. I'd prefer to
change simple things like

-   BufferStorage::iterator it = bstore.begin();
-   BufferStorage::iterator end = bstore.end();
-   for (; it != end; ++it) {
-   Buffer * buf = *it;
+   for(Buffer * buf : bstore)

which are not related to removal of std::bind first.


Yes, that's a good idea.



I have split the patch in two for you, and already committed the part
that does not introduce lambda expressions. Attached is the remainder of
the patch that replaces all remaining std::bind with lambda expressions.





Apart from that I am not too familiar with lambdas yet, so for me personally
the new code is more difficult to read than the old one ATM, and I am
probably not the only one. Your explanation to Richard is nice, but it will
soon be buried in email archives, and people reading LyX sources do not see
it.

I am not opposed to using lambdas (I hope I can learn soemthing from you
here), but I believe that our developer documentation should contain a short
motivation why they are used in LyX (you basically explained already to
Richard how they make code more readable), and a pointer to a more detailed
introduction to lambdas. Then it should also be possible for novices or old-
timers like me to understand the new hot stuff.


It wouldn't hurt to put some comments in the code, too.



I am happy to explain my code to anybody who asks. However, I am not
going to introduce a motivation for lambda expressions in the developer
manual nor add links to introductions. The old code was already using
anonymous functions; that lambda expressions is better for anonymous
functions is obvious to anybody familiar with lambda expressions; and
the documentation is not meant to be a tutorial for ISO C++.

Neither am I going to add comments to the code affected by the patch,
because nobody felt like requiring such comments for the old code.
Whereas the std::bind version can be hard to read for anybody, the new
code is self-explanatory for anybody familiar with lambda expressions,
and comments are again not meant to explain the language.

If other developers are not familiar with lambda expressions yet, then
it is appropriate to wait before committing. Given that I do not know
the source of my issue with gcc 4.6, it is appropriate to wait that
support for gcc 4.6 is dropped (probably about a year from now).

But if anybody needs to use std::bind in the future, please consider the
small investment of learning the simpler lambda expressions and use them
instead. By showing you examples of correspondence between the old codes
and the new, I hope that the attached patch will make it easier for you.

Thank you for your feedback.


Guillaume
>From bd2634b6ae1f92939d8daa65468a8479e4d02385 Mon Sep 17 00:00:00 2001
From: Guillaume Munch 
Date: Wed, 29 Jun 2016 11:40:28 +0100
Subject: [PATCH] Remove support/functional.h and support/bind.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Replace std::bind() with lambdas. This provides a much more readable code.

> It would help me if you could explain this new syntax. [...]
>
>> -theApp()->registerSocketCallback(fd,
>> -bind(::read_ready, this));
>> +theApp()->registerSocketCallback(fd, [this]() { read_ready(); });
>

In C++11, the syntax [X](Y){Z} is called a “lambda expression” and
denotes an anonymous function.

The (Y) is the list of arguments, with which you are already familiar in
function declarations, e.g. (std::string const & str). The {Z} is what
you would write in the body of such function (including the return
statement). It goes without saying that in the end, this is much
more readable and expressive than creating anonymous functions with
std::bind.

The power of the lambda expressions comes from the [X] parameter. Inside
Z, you can refer and access to any variable that you can already access
and refer to in the scope in which you write the lambda expression. For
instance, I wrote above "read_ready();" because I am essentially in the
scope of a member function of LyXComm, and therefore I can refer to (and
omit) "this->".

Now, the expression {Z} can be evaluated much later, and therefore all
the local variables it refers to may already have been destroyed.
Therefore we need the parameter [X] to indicate how the free variables
appearing in {Z} but not in (Y) are stored when creating the anonymous
function ("captured", in C++-speak). They are either stored by copying
or stored by reference. [X] is a list of variables possibly prefixed by
&, denoting a reference. For instance [x,,z] means that x and z are
copied and stored with the anonymous function on creation, whereas y is

Re: Anonymous functions: replace bind with lambdas

2016-06-27 Thread Richard Heck
On 06/27/2016 04:14 PM, Georg Baum wrote:
> Guillaume Munch wrote:
>
>> Dear list,
>>
>>
>> Here is a patch that removes all uses of std::bind and boost::bind in
>> src/. I think this is something that we want in the long term, because
>> it makes the changed code much more readable and maintainable.
> You mean std::bind, or did I miss any remaining boost::bind?
>
>> I am conflicted about it, be cause I would like to be eventually able to
>> read and maintain things that have to do with concurrency, but I would
>> not like to introduce hard-to-debug crashes. It no longer crashes for
>> me, but I did not understand the cause of the previous crash.
>>
>> Any advice? Also, since this touches a lot of sensitive code it would
>> not hurt if someone offered to proof-read it.
> For me personally the patch is too big to proof-read it. I'd prefer to 
> change simple things like
>
> -   BufferStorage::iterator it = bstore.begin();
> -   BufferStorage::iterator end = bstore.end();
> -   for (; it != end; ++it) {
> -   Buffer * buf = *it;
> +   for(Buffer * buf : bstore)
>
> which are not related to removal of std::bind first.

Yes, that's a good idea.

> Apart from that I am not too familiar with lambdas yet, so for me personally 
> the new code is more difficult to read than the old one ATM, and I am 
> probably not the only one. Your explanation to Richard is nice, but it will 
> soon be buried in email archives, and people reading LyX sources do not see 
> it.
>
> I am not opposed to using lambdas (I hope I can learn soemthing from you 
> here), but I believe that our developer documentation should contain a short 
> motivation why they are used in LyX (you basically explained already to 
> Richard how they make code more readable), and a pointer to a more detailed 
> introduction to lambdas. Then it should also be possible for novices or old-
> timers like me to understand the new hot stuff.

It wouldn't hurt to put some comments in the code, too.

Richard



Re: Anonymous functions: replace bind with lambdas

2016-06-27 Thread Georg Baum
Guillaume Munch wrote:

> Dear list,
> 
> 
> Here is a patch that removes all uses of std::bind and boost::bind in
> src/. I think this is something that we want in the long term, because
> it makes the changed code much more readable and maintainable.

You mean std::bind, or did I miss any remaining boost::bind?

> I am conflicted about it, be cause I would like to be eventually able to
> read and maintain things that have to do with concurrency, but I would
> not like to introduce hard-to-debug crashes. It no longer crashes for
> me, but I did not understand the cause of the previous crash.
> 
> Any advice? Also, since this touches a lot of sensitive code it would
> not hurt if someone offered to proof-read it.

For me personally the patch is too big to proof-read it. I'd prefer to 
change simple things like

-   BufferStorage::iterator it = bstore.begin();
-   BufferStorage::iterator end = bstore.end();
-   for (; it != end; ++it) {
-   Buffer * buf = *it;
+   for(Buffer * buf : bstore)

which are not related to removal of std::bind first.

Apart from that I am not too familiar with lambdas yet, so for me personally 
the new code is more difficult to read than the old one ATM, and I am 
probably not the only one. Your explanation to Richard is nice, but it will 
soon be buried in email archives, and people reading LyX sources do not see 
it.

I am not opposed to using lambdas (I hope I can learn soemthing from you 
here), but I believe that our developer documentation should contain a short 
motivation why they are used in LyX (you basically explained already to 
Richard how they make code more readable), and a pointer to a more detailed 
introduction to lambdas. Then it should also be possible for novices or old-
timers like me to understand the new hot stuff.


Georg



Re: Anonymous functions: replace bind with lambdas

2016-06-27 Thread Guillaume Munch

Le 26/06/2016 21:17, Richard Heck a écrit :

It would help me if you could explain this new syntax. I'm a philosopher, not a 
programmer.


-theApp()->registerSocketCallback(fd,
-bind(::read_ready, this));
+theApp()->registerSocketCallback(fd, [this]() { read_ready(); });





Hi Richard

Thank you for asking. (I think you forgot to send the above one to the
list.)

In C++11, the syntax [X](Y){Z} is called a “lambda expression” and
denotes an anonymous function. The name and the concept is directly
taken from the λ-calculus, which may already be familiar to
philosophers, linguists, and mathematicians in the room (and of course
to computer scientists). Interestingly, the first name to come up in
“The Lambda Calculus”¹, Stanford Encyclopedia of Philosophy,
Section 3: “Brief history of λ-calculus” is Frege.
(¹)

The (Y) is the list of arguments, with which you are already familiar in
function declarations, e.g. (std::string const & str). The {Z} is what
you would write in the body of such function (including the return
statement). It goes without saying that in the end, this is much
more readable and expressive than creating anonymous functions with
std::bind.

The power of the lambda expressions comes from the [X] parameter. Inside
Z, you can refer and access to any variable that you can already access
and refer to in the scope in which you write the lambda expression. For
instance, I wrote above "read_ready();" because I am essentially in the
scope of a member function of LyXComm, and therefore I can refer to (and
omit) "this->".

Now, the expression {Z} can be evaluated much later, and therefore all
the local variables it refers to may already have been destroyed.
Therefore we need the parameter [X] to indicate how the free variables
appearing in {Z} but not in (Y) are stored when creating the anonymous
function ("captured", in C++-speak). They are either stored by copying
or stored by reference. [X] is a list of variables possibly prefixed by
&, denoting a reference. For instance [x,,z] means that x and z are
copied and stored with the anonymous function on creation, whereas y is
stored as a reference to the original object.

In the example above, I refer (implicitly) to "this" and therefore I
must indicate that this (the pointer) is to be copied.

There are two shorthand syntaxes for [X]: [=,...] and [&,...]. =
indicates that all remaining free variables must be copied. & indicates
that all remaining variables must be stored by reference. (In both cases
the this pointer will be copied, not stored by reference.)



+namespace {
+
+template
+typename std::result_of::type call(F f) {
+#if EXPORT_in_THREAD
+return call_in_gui_thread(f);
+#else
+return f();
+#endif
+}
+
+} // anon namespace
+
+
  void noAppDialog(QString const & title, QString const & msg, 
QMessageBox::Icon mode)
  {
  int argc = 1;
@@ -136,13 +150,10 @@ int prompt(docstring const & title0, docstring const & 
question,
docstring const & b1, docstring const & b2,
docstring const & b3, docstring const & b4)
  {
-#ifdef EXPORT_in_THREAD
-return InGuiThread().call(,
-#else
-return doPrompt(
-#endif
-title0, question, default_button,
-cancel_button, b1, b2, b3, b4);
+return call([&, default_button, cancel_button] () {
+return doPrompt(title0, question, default_button,
+cancel_button, b1, b2, b3, b4);
+});
  }




In the above example, I first added a function call_in_gui_thread in
InGuiThread, which takes a function with signature R(), executes it in
the GUI thread, and returns the result of type R. This is all that we
need, now that anonymous functions of type R() are easy to create,
thanks to lambda expressions.

Then for simplicity I moved all the #ifdefs inside call() which is a
wrapper to call_in_gui_thread(). So above, call() is essentially
call_in_gui_thread() as I just described.

The function passed to call() reads as follows:

1. Pass the eight arguments to doPrompt and return the result (so prompt
is essentially a wrapped for doPrompt. One could in fact now move the
whole contents of doPrompt inside the anonymous function, but I did not
do it.)

2. The eight arguments are stored as follows until the function is
destroyed (after the actual call): default_button, cancel_button, and
this are copied, and all the other variables are stored by reference.



+   auto compile = [=](std::string const & s) {
+   return clone->doExport(s, true);
+   };
+   return runAndDestroy(compile, orig, clone, format);


(I corrected the above because I think there was an error — which
unfortunately does not explain my initial problem.)

In the above example, the function "compile" calls clone->doExport where
"clone" is a copy of to the original pointer "clone", and where the
first argument is passed to it later by 

Re: Anonymous functions: replace bind with lambdas

2016-06-26 Thread Richard Heck

On 06/26/2016 03:20 PM, Guillaume Munch wrote:

+   auto compile = [&](std::string const & s) {
+   return clone->doExport(s, true);
+   };
+   return runAndDestroy(compile, orig, clone, format);


This one, too, and the other auto one that follows it.

rh



Re: Anonymous functions: replace bind with lambdas

2016-06-26 Thread Richard Heck


Some explanatory comments in this stuff would help, too. These complex 
constructions are nice in reducing code, but they are hard for novices 
to read without help.


rh


On 06/26/2016 03:20 PM, Guillaume Munch wrote:

+namespace {
+
+template
+typename std::result_of::type call(F f) {
+#if EXPORT_in_THREAD
+   return call_in_gui_thread(f);
+#else
+   return f();
+#endif
+}
+
+} // anon namespace
+
+
  void noAppDialog(QString const & title, QString const & msg, 
QMessageBox::Icon mode)
  {
int argc = 1;
@@ -136,13 +150,10 @@ int prompt(docstring const & title0, docstring const & 
question,
  docstring const & b1, docstring const & b2,
  docstring const & b3, docstring const & b4)
  {
-#ifdef EXPORT_in_THREAD
-   return InGuiThread().call(,
-#else
-   return doPrompt(
-#endif
-   title0, question, default_button,
-   cancel_button, b1, b2, b3, b4);
+   return call([&, default_button, cancel_button] () {
+   return doPrompt(title0, question, default_button,
+   cancel_button, b1, b2, b3, b4);
+   });
  }
  




Re: Anonymous functions: replace bind with lambdas

2016-06-26 Thread Guillaume Munch

As a sidenote: a related feature of Qt5 that is absent from Qt4.8 is the
possibility to connect signals to arbitrary functions (including
anonymous ones such as lambdas).

Pros and cons from https://wiki.qt.io/New_Signal_Slot_Syntax:

Pros
* Compile time check of the existence of the signals and slot, of the
types, or if the Q_OBJECT is missing.
* Argument can be by typedefs or with different namespace specifier, and
it works.
* Possibility to automatically cast the types if there is implicit
conversion (e.g. from QString to QVariant)
* It is possible to connect to any member function of QObject, not only
slots.

Cons
* More complicated syntax? (you need to specify the type of your object)
* Very complicated syntax in cases of overloads? (see below)
* Default arguments in slot is not supported anymore.