Monday, October 15, 2012

Queryable extensions

It is possible to extend a LINQ vocabulary with some custom methods that will be used later in query providers to build a custom query to outer source. Also, there is a little trick that allows using such extensions in Linq-to-objects expressions.

Here is a standard stub for an IQueryable method:


public static IQueryable<Tuple<int, TKey>> CountBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
{
    return source.Provider.CreateQuery<Tuple<int, TKey>>(
            Expression.Call(
              null,
              ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)),
              new[] { source.Expression, Expression.Quote(keySelector) }
                                                       ));
}

To add this methods for LINQ-to-Object you have to add the method for IEnumerable as well with same parameters (just replace Expression<Func<...>> with Func<...>) to the same type where IQueryable method is defined:


public static IEnumerable<Tuple<int,TKey>> CountBy<TSource,TKey>(this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
{
    return source.GroupBy(keySelector).Select(x => Tuple.Create(x.Count(), x.Key));
}


Friday, September 21, 2012

Pearls of scala I - By-name parameters

In C# there is no way to define short-circuit evaluated 'and' function (for example).

The naive implementation like following is not good enough.

bool And(bool a, bool b){
  if (a)
    return b;
  else 
    return false;
}

Let define an identity function:


bool Id(bool value){
  Console.WriteLine(value);
  return value;
}


And let's compare output of the following statements:

And(Id(false),Id(false))    and    Id(false) && Id(false)

The first statement will produce:
False
False

The second one:
False

The second statement will not be fully evaluated. As far as first operand of && returns false, the statement evaluates to false regardless of second operand.

Instead the first one have to evaluate both parameters before evaluating the method body.

The only way to imitate the short-circuit evaluation is to pass ugly Action<bool> as a second parameter:


bool And(bool a, Action<bool> b){
  if (a)
   return b();
  else 
    return false;
}

var result = And(Id(false), ()=>Id(false));

In Scala, by-name parameters are part of language, so we could easily transform long-circuit 'and' function to  a short-circuit with minimum changes in function definition and without any changes in function usages:


Long-circuit:

def and(a:Boolean, b:Boolean) = if (a) b else false

Short-circuit:

def and(a:Boolean, b: => Boolean) = if (a) b else false

'=> Boolean' states for 'by-name' parameter, it would be evaluated only in function body as many times as requested (even zero, like in 'and(false,someLongFunction())')




Wednesday, May 30, 2012

MakeGenericType

When does the following line of code could fail with "The number of generic arguments provided doesn't equal the arity of the generic type definition"?


var t = typeof (SomeGenericClass<,,>).MakeGenericType (typeof (int), typeof (int), typeof (int));

Where SomeGenericClass is defined as:

public class SomeGenericClass<TT1T2>
{
}

Answer (thx for Elena):

If SomeGenericClass is defined inside another generic type, its generic types arguments will consist of root type generic arguments and its own generic arguments. MakeGenricType will cut of all generic type arguments, so you have to provide types for base type definition too:


public class SomeRootClass<T3>
{
  public class SomeGenericClass<TT1T2>
  {
  }
...

var t = typeof (SomeGenericClass<,,>).MakeGenericType (typeof (T3), typeof (int), typeof (int), typeof (int));
...
}

Thursday, May 24, 2012

Reverse

Three tiny puzzles:
  1. Given the following interface:

    interface
     INode
    {
             INode Next { getset; }
             object Data { get; }
    }

    and a reference to root 
    INode root reverse a one-linked list. Do not use any additional collections, as arrays, lists or stacks.
    
    
  2. The same for this interface:

    interface INode
    {
             INode Next { get}
             object Data { getset; }
    }

  3. And the same for this:

    interface
     INode
    {
             INode Next { get}
             object Data { get; }
    }
First and second tasks are almost the same, the 3rd solution will be good for 1st and 2nd as well.

Thursday, May 17, 2012

Mix of Queryable and Enumerable

Some useful observation from Expressions world.

Let's imagine we have the following class:


public class Foo
{
 public int[] Items { getset; }
}



And we use it in some IQueryable request in a following manner:


var queryable = new[] { new Foo {Items = new[] { 1, 2, 3 }} }.AsQueryable();

var q = queryable.Select(x => x.Items.Select(y => y % 2 == 0));


Note, that Items implements IEnumerable only, so this query is represented as:
var q = Queryable.Select(queryable, x => Enumerable.Select<intbool>(x.Items, y => y % 2 == 0));

Enumerable.Select takes Func<,> as its second parameters and we're expecting that this functor will be transformed into some method. But in this case, functor inside a Select method will be translated in Expressions as well:



ParameterExpression CS1 = Expression.Parameter(typeof(Foo), "x");
ParameterExpression CS3 = Expression.Parameter(typeof (int), "y");

MemberExpression memberExpression = Expression.Property(CS1, items);
IQueryable<IEnumerable<bool>> q1 = queryable.Select(
  Expression.Lambda<Func<FooIEnumerable<bool>>>(
    Expression.Call(null, select, new Expression[]
      {
        memberExpression,
        Expression.Lambda<Func<intbool>>(
          Expression.Equal(
            Expression.Modulo(CS3,
                              Expression.Constant(2, typeof (int))),
            Expression.Constant(0, typeof (int))), new[] {CS3})
      }), new[] {CS1}));
The same could be used for creating your own Expressions - if you use methods that accept functors, do not compile them in place, just insert as Expression.Lambda.

Note, that if Items implement IQueryable rather than IEnumerable, the nested Lamba expression will be quoted:
 
public class Bar
{
 public IQueryable<int> Items { getset; }
}
var queryable = new[] { new Bar {Items = new[] { 1, 2, 3 }.AsQueryable()} }.AsQueryable();

var q = queryable.Select(x => x.Items.Select(y => y % 2 == 0));

ParameterExpression CS1 = Expression.Parameter(typeof(Foo), "x");
ParameterExpression CS3 = Expression.Parameter(typeof (int), "y");

MemberExpression memberExpression = Expression.Property(CS1, items);
IQueryable<IEnumerable<bool>> q1 = queryable.Select(
  Expression.Lambda<Func<FooIEnumerable<bool>>>(
    Expression.Call(null, select, new Expression[]
      {
        memberExpression, Expression.Quote(
        Expression.Lambda<Func<intbool>>(
          Expression.Equal(
            Expression.Modulo(CS3,
                              Expression.Constant(2, typeof (int))),
            Expression.Constant(0, typeof (int))), new[] {CS3})
        )
      }), new[] {CS1}));
And this is the only purpose for Expression.Quote method.

Tuesday, May 8, 2012

Two cool regex features


Unicode Character Properties

\p{spec}


where spec - various specs definitions like:

  • L - letter
  • Ll - lowercase letter
  • P - punctuation
  • Cyrillic - Cyrillic letter
  • InSpecials: U+FFF0..U+FFFF
... and much more.

Character Class Subtraction

Example:


[a-z-[aeiuo]]


A single letter is not a vowel.


Could be combined with Unicode character properties: 

non-English letters - [\p{L}-[\p{IsBasicLatin}]]


More examples here



Saturday, May 5, 2012

Delegate sum

Funny trick via http://confluence.jetbrains.net/display/ReSharper/Delegate+subtraction+has+unpredictable+semantics


Action a = () => Console.Write("A");
Action b = () => Console.Write("B");
Action c = () => Console.Write("C");
Action s = a + b + c + Console.WriteLine;
s(); //ABC
(s - a)(); //BC
(s - b)(); //AC
(s - c)(); //AB
(s - (a + b))(); //C
(s - (b + c))(); //A
(s - (a + c))(); //ABC

s = a + b + a;
(s - a)(); // AB

Thursday, April 26, 2012

Private const

Some odd attribute defining behavior.

Let's define a class with some constants:

class Foo

{
       public const string String = "some string";
       protected const Type Type = null;
       private const int Int = 42;
}

It's strange but you can access these constants in attribute definition, even protected and public, even without class name specialized!

[MyAttribute(String, Int, Type)]
class Foo
{
       public const string String = "some string";
       protected const Type Type = null;
       private const int Int = 42;
}

class MyAttribute :Attribute
{
       public MyAttribute(string someString, int someInt, Type someType)
       {             
       }
}

Note, that Type constant could be set to null only, because constant initializer must be compiler-time constant and even typeof(Foo) is not a compile-time constant. But it is possible to use typeof(Fooin attribute definition:


[MyAttribute(StringInt typeof(Foo))]
class Foo
{
       public const string String = "some string";
       protected const Type Type = null;
       private const int Int = 42;
}


MyMacro

How to fix Visual Studio Macros IDE crashing from here:


2.1.7 On computers on which Visual Studio 2008 or SQL Server 2008 is installed and Visual Studio 2010 has been uninstalled and then reinstalled, using the Visual Studio Macros IDE may cause Visual Studio to crash

Uninstalling Visual Studio 2010 also removes the Visual Studio Macro Tools package. If the computer also has Visual Studio 2008 or SQL Server 2008, then reinstalling Visual Studio 2010 does not reinstall the Visual Studio Macro Tools package. This causes an error when the Macros IDE is started, and Visual Studio crashes if you try to recreate the MyMacros.vsmacros project.
To resolve this issue:
  1. Delete the following file:
    •     On a 64-bit operating system: "%ProgramFiles(x86)%\Microsoft Visual Studio 9.0\Common7\IDE\1033\Microsoft.VSDesignerUI.dll"
    •     On a 32-bit operating system: "%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\1033\Microsoft.VSDesignerUI.dll"
  2. On the Add or Remove programs page, select Uninstall/Change Visual Studio 2010 and then click Next.
  3. Select Add or Remove features.
  4. Clear and then re-select any of the features in the list.  This causes the update state to be enabled.
  5. Finish the Setup wizard. Visual Studio Macro Tools should be installed.

Wednesday, April 25, 2012

Tail recursion

Some odd behavior to keep in mind.

The following code is expected to fail with StackOverflowException:


class Program
{
       static void Main(string[] args)
       {
              Tail();
       }

       private static void Tail()
       {
              Tail();
       }
}

And it actually fails in all build configuration, except "Release - x64". In this configuration .NET 4 enables the tail recursion optimization, so the Tail() function just hangs.


You can find more info about tail recursion optimization here.

Monday, April 9, 2012

Lazy tree

Some stupid task about Expression trees.

Write down a simplest expression tree visitor (inherited from System.Linq.Expressions.ExpressionVisitor) that will have a static method:

public static IEnumerable<Expression> All(Expression node)

This method should return lazy enumeration of all expression in a an expression tree represented by node. By "lazy" I mean that a tree should not be entirely flattered into a list like this:


class NonLazyVisitor : ExpressionVisitor
{
       readonly List<Expression> _nodes = new List<Expression>();
       public static IEnumerable<Expression> All(Expression node)
       {
              var visitor = new NonLazyVisitor();
              visitor.Visit(node);
              return visitor._nodes;
       }
       public override Expression Visit(Expression node)
       {
              _nodes.Add(node);
              return base.Visit(node);
       }
}


This visitor will traverse entire expression tree - the Visit() method will be called on every node regardless of how much nodes I really want to visit. The task is to minimize the footprint and visit as less nodes as possible.

The lazy visitor should return expressions in the same order as NonLazyVisitor above.