Implementing reactive programming / functions in C #

I recently read about the design of a game engine and eventually came across this: What is (functional) reactive programming?

I was wondering how to accurately implement the example given in the second highest ranking. In C ++, it would be easy enough to pass a pointer to a value that stores the coordinates of the mouse, and simply return the value of this instead of int. Well, we cannot do this in C #, so our first problem. do we need to call some function "update" to update all values?

secondly, how will the syntax be processed? assignment of values ​​is direct. But doing things like “get the mouse position and minutes 14 from him every time I ask him” is a little more .. difficult.

and finally, I was wondering how you would make any object in C # return a value when you reference it directly. for example

int test = 1; 

test will return 1. So, I can do things like 1 + test, which will = 2

but if I had an instance

 public class ReactiveInt { int myValue } 

I can't just do what I did above when I try to add int together.

Sorry for such a broad question, I think. If you can give a simple example that demonstrates functionality similar to what was discussed in this answer, I think that all my questions will be answered.

+7
source share
3 answers

Questions

Question 1

I can't just do what I did above when I try to add int together.

Well, that’s actually the point. In reactive programming, you do not want to add two numbers in series together, instead you want to define a new number in terms of other numbers. Therefore, c = a + b , such c always equal to a + b , even if a or b changes: c is reactive with respect to a and b .

 var a = new BehaviorSubject(3); var b = new BehaviorSubject(1); var c = Rx.Observable.combineLatest(a, b, function(vals) { return vals[0] + vals[1]; }); 

Question 2

I was wondering how to accurately implement the example given in the second highest ranking.

The simple answer is lists and higher order functions in haskell.

Answer that you do not want Functional-reactive programming goes against what you learned in imperative programming, and you will have to relearn how to do things if you want to do purely functional reactive programming. If you do not, you will end up creating all kinds of dependency tracking libraries like KnockoutJS , when you can do the same in a few hundred lines with something like RxJS-Splash if you used FRP to get you started. (note that Splash is based on Rx, which is reusable code, and Knockout is exclusively implementation-specific code).

FRP has the concept of events and time, while dependency tracking has the concept of values ​​and changes. The functional reactive code was about the same as the imperative code. It is not "built on top of an imperative code." (yes, it still compiles to assembly ... not so), it’s important .

Example

Using Microsoft Reactive Extensions for JavaScript ( RxJS )

Keep in mind that Rx is now available in many languages, including native C ++ .

Direct port example

 var moves = $(document).onAsObservable('mousemove') .map(function(e) { return { x: e.pageX, y: e.pageY }; }); var xs = moves.map(function(move) { return move.x; }); var ys = moves.map(function(move) { return move.y; }); var minXs = xs.map(function(x) { return x - 16; }); var minYs = ys.map(function(y) { return y - 16; }); var maxYs = xs.map(function(x) { return x + 16; }); var maxYs = ys.map(function(y) { return y + 16; }); var boundingRect = Rx.Observable.combineLatest(minXs, minYs, maxXs, maxYs) .map(function(vals) { var minX = vals[0]; var minY = vals[1]; var maxX = vals[2]; var maxY = vals[3]; return new Rectangle(minX, minY, maxX, maxY); }); 

Simplified port

Since a rectangle is defined only in terms of one dependent value (or event), you can simplify this to the following:

 var boundingRect = $(document).onAsObservable('mousemove') .map(function(e) { var x = e.pageX; var y = e.pageY; return new Rectangle(x - 16, y - 16, x + 16, y + 16); }); 

Using

At this point, you can use it to compose other observable sequences (values ​​that change over time).

 var area = boundingRect.map(function(rect) { return rect.getSize(); }); 

Or subscribe to it directly.

 boundingRect.subscribe(function (rect) { // perform some action with the rect each time it changes. console.log(rect); }); 

But this is only when it changes!

What if we want to get the latest value as soon as we sign, instead of waiting for the rectangle to change again? Well, where is BehaviorSubject .

 var rects = new Rx.BehaviorSubject(new Rectangle(-1, -1, 1, 1)); rects.subscribe(function(rect) { // this would happen twice in this example. // Once for the initial value (above), and once when it is changed later (below). console.log(rect); }); rects.onNext(new Rectangle(-1, -1, 1, 1)); 

But this is not the original, observed, and it is not very functional ...

Here's how to do the same with the original observable, using some built-in functions to change to Observable, to act like a BehaviorSubject ...

 var rectsAndDefault = rects.startWith(new Rectangle()); // just give it an initial value rectsAndDefault.subscribe(function(rect) { console.log(rect); // happens once for the "startWith" rectangle, and then again for all subsequent changes }) 

Again, FRP is different. This is good, but it is a big task to learn. You will learn that you began to receive it when it begins to choke.

+8
source
+1
source

Using Lambdas and Actions as an event handler, you can get away without pointers.

 int Offset = 16; int Size = Offset * 2; Action<MouseEventArgs> MouseEventArgsHandler = (args) => DrawRectangle(args.x - Offset, args.y - Offset, Size, Size); 
0
source

All Articles