Introducing Elevate

The past few weeks, a few other SRT Solutions developers and I have been working on a new open source library called Elevate. We went public with the source on CodePlex this weekend, and although we’re still in the early stages of development, I already rely on many of the functional programming features of the library in my day to day coding. So, without further ado, I’d like to formally announce the Elevate project.

What Is Elevate?

Let’s face it, no library has it all, and the BCL is no exception. If you’re anything like me, then you occasionally find yourself re-writing some utility methods over and over again for each project that you work on. Even though you know it’s wrong, you probably re-invent the wheel from time to time for “simple” things. Maybe you carry around your own “MyUtilities.cs” file from project to project. Either way, in the back of your mind, you know that there has to be a better way.

For C++ programmers, this void is filled with Boost. Boost contains a lot of functionality that is missing from the C++ STL for one reason or another. It’s a great library for C++ development. But what about us poor C# developers?

That’s where Elevate comes in. Elevate is a Boost-like library for .NET. Our goal at SRT Solutions is to capture the things that we think are missing from the BCL and put them in Elevate so that we can share them between our project groups and the rest of the world. By devoting some of our weekly learning time to add these common bits of code to Elevate, we can save ourselves, our clients, and hopefully other .NET developers time and money.

What do we have so Far?

We can’t add everything overnight, so to start off, we’re focusing on functional programming concepts. We’ve already taken some of the more useful methods and classes from languages like F#, Ruby, and Haskell and added them to our own collection of useful C#  utilities. Here are some of the highlights below:

Building sequences:

[Test]
public void MixingAndMatching()
{
    //if you have a couple sequences of values
    var first = Seq.Build("alpha", "beta");
    var second = Seq.Build("delta", "epsilon");

    //you can combine them along with some other values to create a new sequence
    var result = Seq.Build(first, "gamma", second, "zeta");
 
    var expected = Seq.Build("alpha", "beta", "gamma", "delta", "epsilon", "zeta");
    Assert.AreEqual(expected, result);
}
 
[Test]
public void Through()
{
    //if we want to easily generate a sequence of incrementing numbers,
    //we can do it like this
    IEnumerable<int> numbers = 1.Through(15);

    var expected = Seq.Build(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
    Assert.AreEqual(expected, numbers);
}

“LINQ Extensions”:

[Test]
public void SelectWithIndex()
{
    //given a sequence of values
    var values = 10.Through(50, 10);
 
    //we can apply a selector function to each element based
    //on the element's value and it's index
    var result = values.SelectWithIndex((index, value) =>
                                             value / (index + 1));
 
    var expected = Seq.Build(10, 10, 10, 10, 10);
    Assert.AreEqual(expected, result);
}

[Test]
public void Chunk()
{
    //given a sequence
    var sequence = 1.Through(20);

    //we can split the sequence into a sequence of "chunks" that
    //are each a specific length
    var chunks = sequence.Chunk(5);
 
    var expectedChunks = 
        Seq.Build<IEnumerable<int>>( 
            1.Through(5).ToList(),
            6.Through(10).ToList(),
            11.Through(15).ToList(),
            16.Through(20).ToList());
 
    Assert.AreEqual(expectedChunks, chunks);
}

[Test]
public void Select2()
{
    //given two sequences
    var one = 0.Through(5);
    var two = 2.Through(12, 2);

    //we use Select2 to walk the sequences in parallel and apply a
    //selector function
    var result = one.Select2(two, (elementFromFirst, elementFromSecond) => 
            elementFromFirst * elementFromSecond);

    var expected = Seq.Build(0, 4, 12, 24, 40, 60);
    Assert.AreEqual(expected, result);
}

Pattern Matching:

 [Test]
public void PatternMatchingWithFunctions()
{
    //given a value
    var value = "alpha";

    //we can start a pattern match like this
    var result = value.Match()
        //causes the pattern match to return "empty" if value is null or empty
        .With(string.IsNullOrEmpty, stringValue => "empty")
        //match any string containing "a"
        .With(stringValue => value.Contains("a"), stringValue => "contains a!")
        .EndMatch();
 
    Assert.AreEqual("contains a!", result);
}

[Test]
public void EasierTuplePatternMatching()
{
    //given a tuple
    Tuple<string, int> tuple = Tuple.Create("Da Bears", 2); 

    //We can avoid having to specify the arguments explicitly for the
    //match portion of the predicate like this
    var result = tuple.Match()
        .WithSecond(1, (teamName, wins) => wins + 1)
        .WithFirst("Da Bears", (teamName, wins) => wins)
        .EndMatch();

    Assert.AreEqual(result, 2);
}

Option Types:

[Test]
public void OptionTypesCanContainValues()
{
    //given a value
    var value = 10;
 
    //we can wrap it in an option type like this
    Option<int> option = Option.Some(value);
 
    Assert.IsTrue(option.IsSome);
    Assert.IsFalse(option.IsNone);
    Assert.AreEqual(10, option.Value);
}

[Test]
public void MultipleOpertionsWithOptionTypes()
{
    //say we have a few functions that may or may not return a value.
    Func<int, Option<int>> divideIfEven = value =>
        ((value % 2) == 0) ? Option.Some(value / 2) : Option<int>.None;

    Func<int, Option<int>> subtractIfDivisibleByThree = value =>
        ((value % 3) == 0) ? Option.Some(value - 3) : Option<int>.None;

    Func<int, Option<int>> multiplyIfOdd = value =>
        ((value % 2) != 0) ? Option.Some(value * 2) : Option<int>.None;
 
    //we can chain these operations together like this:
    Option<int> result =
        divideIfEven(36)
        .Select(subtractIfDivisibleByThree)
        .Select(multiplyIfOdd);

    //the result of one carries on to the next to yield the expected result
    Assert.IsTrue(result.IsSome);
    Assert.AreEqual(30, result.Value);
}

These are just a few samples of the things you can do with Elevate, but there is a lot more to play around with in the actual library. Hopefully, you’re convinced that there are already a number of interesting functional programming features.

Moving Forward

If you’re interested in the above samples, head on over to http://elevate.codeplex.com and check out the source. All of the above samples are copied right out of the “Elevate.Guide” test project. We wrote this project with the goal that someone who has no experience with Elevate can get up and running quickly just by reading through it.

Over the next few weeks, I will try to post about some of the features in Elevate in more detail. If you’re a C# programmer interested in functional programming, a functional programming guru who wants to see examples of functional programming in C#, or simply someone interested in seeing cool and useful language extensions, stay tuned for more detailed posts.

Finally, we would love to hear any feedback (good or bad) and any feature requests that you might have. There are a number of ways to get in contact with us. You can submit comments below, start a discussion or submit a review on the CodePlex page, send an email through CodePlex, or send me a tweet (my username is ChrisMarinos on CodePlex and twitter). Also, speaking of Twitter, be sure to follow @elevateproject for updates!

Update: Check out our GoogleGroup at http://groups.google.com/group/ElevateProject!

This entry was posted in C#, Elevate, F#, Functional, SrtInsights. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

5 Comments

  1. alimbada
    Posted October 15, 2009 at 1:27 pm | Permalink

    I think everyone would be better off if you contributed to Mono.Rocks (http://www.mono-project.com/Rocks) rather than duplicating effort in this manner.

  2. Doug.UK
    Posted October 16, 2009 at 9:02 am | Permalink

    I agree about the ” duplicating effort” risk as all that will give us is the VHS/Betamax war later. Cool that you are bothered to explore, research this. With luch the best of both will get consolidated into something better.
    I would like to point out that zinngyRed on gray is not that visible, eg look at “# Niki said on 13 October, 2009 03:21 AM ” post.

  3. GioL
    Posted November 9, 2009 at 10:23 am | Permalink

    awesome tool. This could save time in first stage of development. Thanks

  4. Amit
    Posted November 25, 2009 at 7:06 pm | Permalink

    Excellant work..Thanks for sharing

  5. Matthias Broschk
    Posted December 2, 2009 at 12:32 am | Permalink

    Thank you, great works, with these continuous developments I am really curious abous how a ‘common’ C# code piece will look like in 5-10 years.

One Trackback

  1. […] This post was mentioned on Twitter by Kevin Dente, Jay R. Wren, Sam Merrell, Anders Bratland, Alan and others. Alan said: RT @kevindente: Elevate (C# library) looks pretty cool – http://goo.gl/E3Ahf […]

Post a Comment

Your email is never published nor shared. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*
*