Vedea := :=: :== operators and their use

bearophile bearophileHUGS at lycos.com
Fri Aug 5 12:06:05 PDT 2011


Some people at Microsoft is (or was) working at the Vedea language. It's a bit like the Processing language, but it's more vectorial, more based on graphical objects (like the Tk GUI toolkit), it runs on DotNet:
http://blogs.msdn.com/b/martinca/archive/2009/12/03/introducing-the-microsoft-visualization-language.aspx

What's nice are its := :=: :== operators and the way they are used (but in my opinion you work far less adding those three operators to a custom version of IronPython). Quotation of the part about them:

--------------

Another unique aspect of the language is its implementation of bindings.  You might be familiar with bindings from WPF and Silverlight, and the concept here is similar, though expanded.  The simplest example of a binding is as follows:

    textbox.Text := slider.Value;

This is a 'binding' that you call once in your program, but which 'forever' binds the value of the slider to the text in the textbox.  If the slider is moved, the text will change to match the current slider value.  Since bindings can be cancelled, 'forever' really means 'until you do something to cancel the binding.

You can also do the following:

    textbox.Text :=: slider.Value;

In this case, if you move the slider, the textbox's text will change, but if you type a value in the textbox, the slider will change to match that value.  Text and slider values are of different types, so some value conversion is happening under the covers here.

Things get much more interesting when you combine bindings with collections defined with LINQ syntax:

    myData = DataSet("mydata.csv");
    currentYear := slider.Value + 1900;
    bubbles := from row in myData 
      where row.Year :== currentYear 
      select new Circle() 
        { 
          X = row.Latitude, 
          Y = row.Longitude, 
          Radius = row.Population * scalingFactor, 
          Fill = BlackBodyPalette(1., 1., row.DeltaCarbon) 
        };
    Scene["USMap"].Add(bubbles);

The first line connects the variable 'myData' to the dataset in mydata.csv. The CSV file contains columns for Year, Latitude, Longitude, Population and DeltaCarbon (possibly in addition to other columns) which is why we can access those columns as if they were properties of 'row'.

The second line binds the variable currentYear to the slider's value plus 1900. As the slider is moved by the user, currentYear will get updated.

The third line creates a collection of circles ('bubbles'), one for each row in the csv file whose Year value matches currentYear. The Boolean comparison :== is the same as == except that the Boolean value is bound to both variables in the conditional expression. A change to either variable in the comparison will invalidate the comparison, which will cause the collection to be re-evaluated. As a result, as the user moves the slider, the visual collection of bubbles will get updated to reflect the current year's data. (nb: an identifier column can be specified in order to obtain least-flow visualizations or transitional animations). Using '==' instead of ':==' would have resulted in a one-time comparison and the collection would not be updated as the slider is moved (which might be desirable in some cases). In the 'select' portion of the LINQ expression, we create the circles and set their properties based on values found in that row of the data. So as you move the slider, not only will bubbles move and change size and color, but the number of bubbles that are visible will change based on the outcome of the 'where' clause.

Finally, we add the entire collection of bubbles to some member of the scenegraph called 'USMap'.  Presumably that is one of our map objects and adding the collection as a child of that map will use the map's lat/lon coordinate system and position the bubbles according to the lat/lon values found in X and Y.

The end result is that we have produced an interactive timeline visualization using less than a dozen lines of code (or four statements). It is true that the code is 'denser' – that is, more functionality in less typed space – and consequently a user might spend more time working on fewer lines of code, but we are betting that the number of failure modalities is smaller (fewer ways to mess up); and there's less code 'real estate' to observe and comprehend.  Of course, we still support immediate-mode graphics for anyone who wants to ignore this declarative syntax and create old-school visuals and animations in the render loop.

--------------

Bye,
bearophile


More information about the Digitalmars-d mailing list