none
Rx and Ix Query Comprehension Syntax Keywords in C# RRS feed

  • General discussion

  • Hi everyone,

    Now that C# 5.0 is released, it's time to vote up better Rx integration for C# vNext!

    I've submitted a feature request in Visual Studio UserVoice.  Please add your votes.

    Related discussions:
    http://social.msdn.microsoft.com/Forums/en-US/rx/thread/93f73e47-c559-4c4e-b5a4-af592b678658

    I just responded to a question recently and provided some code that seems like it could benefit from having a few new C# keywords in query comprehension syntax.

    • Consecutive zip statements calls N-Ary Zip, similar to how consecutive from statements call SelectMany.
    • A publish statement with a let mode.  It assigns a new range variable to the argument in the functional Publish operator, and the remainder of the query is within the scope of Publish.
    • A publish statement with a declarative mode.  This is similar to let, but instead of declaring a new range variable it repurposes an existing variable so that all uses before the publish statement remain unpublished and all uses after the publish statement are treated as the argument in the functional Publish operator.

    Here's what the code currently looks like in C# 5.0.  Notice the multi-level nesting really breaks up the flow of the query.

    var alerts =
    	from movement in mergedDeviceMovements
    	group movement by movement.Value.Device into device
    	from alert in
    		device.Publish(publishedDevice =>
    			publishedDevice.Scan(
    				new
    				{
    					Time = DateTimeOffset.MinValue,
    					Movement = new { Device = new { Id = 0, Color = ConsoleColor.White }, Location = 0 }
    				},
    				(previous, movement) =>
    					movement.Timestamp - previous.Time >= alertMinimumDuration
    					? new { Time = movement.Timestamp, Movement = movement.Value }
    					: previous)
    			.DistinctUntilChanged()
    			.Do(indicator => Log(device.Key.Color, "Alert check @ " + indicator.Time.TimeOfDay))
    			.Publish(timer =>
    				from indicator in timer
    				join movement in publishedDevice on timer equals Observable.Empty<Unit>() into window
    				let movements = window.Select(stamp => stamp.Value).StartWith(indicator.Movement)
    				from delta in Observable.Zip(
    					movements.Min(movement => movement.Location),
    					movements.Max(movement => movement.Location),
    					(min, max) => max - min)
    				where delta < alertMaximumDistance
    				select new { Device = device.Key, Delta = delta }))
    	select alert;

    And here's what I'd imagine it could look like with new language keywords.  I believe they greatly improve the readability of the query. Notice that I also published the movements variable, simply because it was much simpler to do using the proposed publish keyword that works similarly to let.

    var alerts = 
    	from movement in mergedDeviceMovements
            group movement by movement.Value.Device into device
    	publish device
    	publish timer = device.Scan(
    		new
    		{
    			Time = DateTimeOffset.MinValue,
    			Movement = new { Device = new { Id = 0, Color = ConsoleColor.White }, Location = 0 }
    		},
    		(previous, movement) =>
    			movement.Timestamp - previous.Time >= alertMinimumDuration
    			? new { Time = movement.Timestamp, Movement = movement.Value }
    			: previous)
    		.DistinctUntilChanged()
    		.Do(indicator => Log(device.Key.Color, "Alert check @ " + indicator.Time.TimeOfDay))
    	from indicator in timer
    	join movement in device on timer equals Observable.Empty<Unit>() into window
    	publish movements = window.Select(stamp => stamp.Value).StartWith(indicator.Movement)
    	zip min in movements.Min(movement => movement.Location)
    	zip max in movements.Max(movement => movement.Location)
    	let delta = max - min
    	where delta < alertMaximumDistance
    	select new { Device = device.Key, Delta = delta }

    - Dave


    http://davesexton.com/blog

    • Changed type Dave Sexton Friday, September 21, 2012 3:55 AM Forgot to make it a discussion
    Friday, September 21, 2012 3:38 AM