Sometimes I have to implement a feature like customized drag & drop. The code may goes like this:
bool mouse_down = false;
Vec2 mouse_pos;
void on_mouse_down() {
mouse_down = true;
mouse_pos = cursor_pos();
}
void on_mouse_move() {
if(mouse_down) {
Vec2f c = cursor_pos();
Vec2f d = c - mouse_pos;
// dragging. make objects tracing the cursor.
// ...
}
}
void on_mouse_up() {
mouse_down = false;
// dropped
// ...
}
I know this works fine, but I donnot like redundant variables and separated procedures for something like this at all. In IP(imperative programming) maybe it's unavoidable; my question is, is there a better way to deal with this kinda thing in FP(functional programming)? Any ideas and suggestions are appreciated, no matter whatever programming languages, Lisp, Scheme, F#, Ruby, etc. or some better way to do this in IP?
Since nobody attempted an answer for a day, I'll give it a shot. I understand the problem that you are discussing, but the answer should likely depend on the operating system, language and its runtime library.
The general idea would be that when mouse goes down, you spawn off an asynchronous computation. This computation "blocks" on events, and processes them in its own loop as fetched, doing what you need to do; it exists when the mouse button does up. While this looks like it works like an imperative thread, in reality, when the computation gets "blocked", it just yields control to where it was started from (the main GUI thread invoking the mouse down event, presumably). In such a way, the state is encapsulated into what looks like a lexically local scope of the computation. That magic has to be handled by the runtime of the language, so this is as far as we can get with the answer in a language ans OS-agnostic way.
As for an example of such implementation, check this answer and an article by Tomas Petricek, both discussing your question but in a narrow setting of Windows, .NET and F#. There is a book by the same Perticek, Real World Functional Programming: With Examples in F# and C#, where the same ideas are expressed, surprisingly, in C#, not usually regarded a functional language. Chapter 16, if my memory serves me, is yours.
As for encapsulating the state in an IP/OO language program, you can create an instance of a class in your mouse_down handler. The instance would register itself with the runtime to receive other mouse and UI events, process them, do all the work and, when needed (mouse goes up or the windowing system cancels capture mode), unregisters and destroy itself. Not as elegant as a functional language would allow, but still much better that keeping mutable state in a general UI class.