caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Adrien <camaradetux@gmail.com>
To: Philippe Veber <philippe.veber@gmail.com>
Cc: "Daniel Bünzli" <daniel.buenzli@erratique.ch>,
	"caml users" <caml-list@inria.fr>
Subject: Re: [Caml-list] Functional GUI programming: looking for good practices
Date: Tue, 14 Feb 2012 12:52:02 +0100	[thread overview]
Message-ID: <CAP5QFJ=6ECGqtK_ZnG_=k5zA=DRVPrzgrPHC6T0f5Wh54QHj3Q@mail.gmail.com> (raw)
In-Reply-To: <CAOOOohRYM3j2osi9mJKmosL+-BgwgLV-V7vUfR7iRMdNeHnj8g@mail.gmail.com>

On 14/02/2012, Philippe Veber <philippe.veber@gmail.com> wrote:
> Hi Daniel,
>
> 2012/2/14 Daniel Bünzli <daniel.buenzli@erratique.ch>
>
>> Le mardi, 14 février 2012 à 11:02, Philippe Veber a écrit :
>>
>> > In other words, am I allowed to call a primitive in a lifted function?
>> No. This is documented here [1].
>
> Well I did read the paragraph, but thought the described limitation might
> be about updating a signal from different threads. Of course it makes sense
> that even in a single-threaded code, an update cycle should not be
> interrupted by another if there are shared dependencies. May I nevertheless
> humbly suggest to add the "not calling a primitive inside a lifted
> function" rule more explicitely, as it is a tempting sin for a beginner?

Quite often, doing so does not make a lot of sense.
Suppose that you have a signal A. An external event triggers an update which
will create A1. But during that update, you trigger another update which
will create A2. Now, how does your signal change? Is A2 going to be the next
value of A or is will it be A1?

A simple (and probably not proper) implementation of FRP that I've done
simply used A2 and then A1: the additional work that had been done for A2
was being dropped.

Some implementations or approaches will probably solve that one way or
another but that's not my point: when you do that, the code becomes
non-obvious.

>> One way to side-step the issue is to put these updates in a queue and
>> execute them after the update cycle ended.
>>
>  That seems a good work-around, to gather all side-effects in one place,
> namely a (unit -> unit) Queue.t where to defer all calls to the primitives.
> That do help, thanks !
> ph.

I've had to use that until I changed the order of some operations in my
code. I might have managed to break a bigger cycle into two smaller and
independant cycles but I need to check, document, triple-check, ... what
I've done.

Anyway, I quickly benchmarked "GLib.Timeout.Add ~ms cb" from gtk/lablgtk2
which calls cb after at least ms milliseconds from the mainloop. Its latency
was around 122µs for ms = 0 in my case (obviously, the program was otherwise
idle).

I think you could also use lwt here but I haven't done anything with it.


Btw, I think it's worthwhile to mention some issues that can create such a
need. In my case of a web browser, web pages have javascript and the
javascript can create a new page and get a corresponding object.
  var popup = window.open (); // or something like that

In webkit-gtk (and probably all other webkit ports), this triggers a GTK
signal to which you can attach a callback which returns a WebView object.
However, my code does not allow a webpage to create a new page: all it can
do is request that one gets created by the Zipper which holds the pages.

So the page changes its state and stores a request for a pop-up from the
callback. The request is seen by the Zipper which creates a new page in the
UI side of my code. Once the page is ready, it gets added to the Zipper and
a message is sent to the parent page. All that has been done in the
callback. It now works with my "MiniFRP" implementation but it definitely
had the A/A1/A2 issue I mentionned above.

If you put the updates in a queue and delay them, you're probably not going
to solve this issue which turns out to be pretty simple. With the callback,
you've started an update cycle and you cannot finish that update cycle
before a new page, and therefore, another update cycle, has taken place.

The API of webkit-gtk could allow to get an ID for the popup request, exit
the callback with only the promise the answer will be given at some point,
and do the actual work outside of the callback. But it doesn't. And there
will always be APIs like that and we need to find how to handle this.


Regards,
Adrien Nader


  reply	other threads:[~2012-02-14 11:52 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-13 11:01 Philippe Veber
2012-02-13 15:27 ` Adrien
2012-02-14 10:02   ` Philippe Veber
2012-02-14 10:21     ` Daniel Bünzli
2012-02-14 10:39       ` Philippe Veber
2012-02-14 11:52         ` Adrien [this message]
2012-02-14 13:00           ` Daniel Bünzli
2012-02-14 13:29     ` Adrien
2012-02-13 18:13 ` Raoul Duke
2012-02-14  0:36   ` Anthony Tavener
2012-02-14 10:17     ` Philippe Veber
2012-02-14 18:02       ` Anthony Tavener
2012-02-15  4:47         ` Anthony Tavener
2012-02-22 11:57           ` Philippe Veber
2012-02-28 10:10             ` Adrien

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAP5QFJ=6ECGqtK_ZnG_=k5zA=DRVPrzgrPHC6T0f5Wh54QHj3Q@mail.gmail.com' \
    --to=camaradetux@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=daniel.buenzli@erratique.ch \
    --cc=philippe.veber@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).