Generation 5 » Linq http://gen5.info/q Towards Intelligent Systems Wed, 20 Jun 2012 15:08:00 +0000 en hourly 1 http://wordpress.org/?v=3.0.3 First-Class Functions and Logical Negation in C# http://gen5.info/q/2009/03/09/first-class-functions-and-logical-negation-in-c/ http://gen5.info/q/2009/03/09/first-class-functions-and-logical-negation-in-c/#comments Mon, 09 Mar 2009 13:50:39 +0000 Paul Houle http://gen5.info/q/?p=253 negation

Introduction

Languages such as LISP,  ML,  oCaml F# and Scala have supported first-class functions for a long time.  Functional programming features are gradually diffusing into mainstream languages such as C#,  Javascript and PHP.   In particular,  Lambda expressions,  implicit typing,  and delegate autoboxing have made  C# 3.0 an much more expressive language than it’s predecssors.

In this article,  I develop a simple function that acts on functions:  given a boolean function fF.Not(f) returns a new boolean function which is the logical negation of f.  (That is,  F.Not(f(x)) == !f(x)).   Although the end function is simple to use,  I had to learn a bit about the details of C# to ge tthe behavior  I wanted — this article records that experience.

Why?

I was debugging an application that uses Linq-to-Objects the other day,  and ran into a bit of a pickle.  I had written an expression that would return true if all of the values in a List<String> were valid phone numbers:

[01] dataColumn.All(Validator.IsValidPhoneNumber);

I was expecting the list to validate successfully,  but the function was returning false.  Obviously at least one of the values in the function was not validating — but which one?  I tried using a lambda expression in the immediate window (which lets you type in expression while debugging) to reverse the order of matching:

[02] dataColumn.Where(s => !ValidatorIsValidPhoneNumber(x));

but that gave me the following error message:

[03] Expression cannot contain lambda expressions

(The expression compiler used in the immediate window doesn’t support all of the language features supported by the full C# compiler.)  I was able to answer find the non matching elements using the set difference operator

[04] dataColumn.Except(dataColumn.Where(Validator.IsValidPhoneNumber).ToList()

but I wanted an easier and more efficient way — with a logical negation function,  I could just write

[05] dataColumn.Except(F.Not(Validator.IsValidPhoneNumber).ToList();

Try 1: Extension Method

I wanted to make the syntax for negation as simple as possible.  I didn’t want to even have to name a class eliminate the need to name a class,  so I tried the following extension method:

[06] static class FuncExtensions {
[07]    public static Func<Boolean> Not(this Func<Boolean> innerFunction) {
[08]       return ()  => innerFunction();
[09]    }
[10]    ...
[11]   }

I was hoping that,  given a function like

[12] public static boolean AlwaysTrue() { return true };

that I could negate the function by writing

[13] AlwaysTrue.Not()

Unfortunately,  it doesn’t work that way:  the extension method can only be called on a delegate of type Func<Boolean>.  Although the compiler will “autobox” function references to delegates in many situations,  it doesn’t do it when you reference an extension method.  I could write

[14] (Func<Boolean> AlwaysTrue).Not()

but that’s not a pretty syntax.   At that point,  I tried another tack.

Try 2: Static Method

Next,  I defined a set of negation functions as static methods on a static class:

[15] public static class F {
[16]    public static Func<Boolean> Not(Func<Boolean> innerFunction) {
[17]       return () => !innerFunction();
[18]    }
[19]
[20]    public static Func<T1,Boolean> Not<T1>(
[21]       Func<T1,Boolean> innerFunction) {
[22]          return x =>!innerFunction(x);
[23]    }
[24]
[25]    public static Func<T1, T2,Boolean> Not<T1,T2>(
[26]       Func<T1, T2,Boolean> innerFunction) {
[27]          return (x,y) => !innerFunction(x,y);
[28]    }
[29]
[30]    public static Func<T1, T2, T3, Boolean> Not<T1,T2,T3>(
[31]       Func<T1, T2, T3, Boolean> innerFunction) {
[32]           return (x, y, z) => !innerFunction(x, y, z);
[33]    }
[34]
[35]    public static Func<T1, T2, T3, T4, Boolean> Not<T1, T2, T3, T4>(
[36]       Func<T1, T2, T3, T4,Boolean> innerFunction) {
[37]          return (x, y, z, a) => !innerFunction(x, y, z, a);
[38]    }
[39] }

Now I can write

[40] F.Not(AlwaysTrue)() // always == false

or

[41] Func<int,int,int,int,Boolean> testFunction = (a,b,c,d) => (a+b)>(c+d)
[42] F.Not(testFunction)(1,2,3,4)

which is sweet — the C# compiler now automatically autoboxes the argument to F.Not on line [40].  Note two details of how type inference works here:

  1. The compiler automatically infers the type parameters of F.Not() by looking at the arguments of the innerFunction.  If it didn’t do that,  you’d need to write
    F.Not<int,int,int,int>(testFunction)(1,2,3,4)

    which would be a lot less fun.

  2. On line [40],  note that the compiler derives the types of the parameters a,b,c, and d using the type declaration on the right hand side (RHS)
    Func<int,int,int,int,Boolean>

    you can’t write var on the RHS in this situation because that doesn’t give the compiler information about the parameters and return values of the lambda.

Although good things are happening behind the scenes,  there are also two bits of ugliness:

  1. I need to implement F.Not() 5 times to support functions with 0 to 4 parameters:  once I’ve done that,  however,  the compiler automatically resolves the overloading and picks the right version of the function.
  2. The generic Func<> and Action<> delegates support at most 4 parameters.  Although it’s certainly true that functions with a large number of parameters can be difficult to use and maintain (and should be discouraged),  this is a real limitation.

Extending IEnumerable<T>

One of the nice things about Linq is that you can extend it by adding new extension methods to IEnumerable.  Not everbody agrees,  but I’ve always liked the unless() satement in Perl,  which is equivalent to if(!test):

[42] unless(everything_is_ok()) {
[43]   abort_operation;
[44] }

A replacement for the Where(predicate) method that negates the predicate function would be convenient my debugging problem:

I built an Unless() extension method that combines Where() with F.Not():

[45] public static IEnumerable<T> Unless<T>(
[46]    this IEnumerable<T> input, Func<T, Boolean> fn) {
[47]       return input.Where(F.Not(fn));
[48]     }

Now I can write

[49] var list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
[50] var filtered = list.Unless(i => i > 3).ToList();

and get the result

[51] filtered = { 1,2,3 }

Conclusion

New features in C# 3.0 make it an expressive language for functional programming.  Although the syntax of C# isn’t quite as sweet as F# or Scala,  a programmer who works with the implicit typing and autoboxing rules of the compiler can create functions that act on functions that are easy to use — in this article we develop a set of functions that negate boolean functions and apply this to add a new restriction method to IEnumerable<T>.

kick it on DotNetKicks.com

]]>
http://gen5.info/q/2009/03/09/first-class-functions-and-logical-negation-in-c/feed/ 0
Using Linq To Tell if the Elements of an IEnumerable Are Distinct http://gen5.info/q/2009/02/13/using-linq-to-tell-if-the-elements-of-an-ienumerable-are-distinct/ http://gen5.info/q/2009/02/13/using-linq-to-tell-if-the-elements-of-an-ienumerable-are-distinct/#comments Fri, 13 Feb 2009 21:15:38 +0000 Paul Houle http://gen5.info/q/?p=213 The Problem

I’ve got an IEnumerable<T> that contains a list of values:  I want to know if all of the values in that field are distinct.  The function should be easy to use a LINQ extension method and,  for bonus points,  simply expressed in LINQ itself

One Solution

First,  define an extension method

01   public static class IEnumerableExtensions {
02        public static bool AllDistinct<T>(this IEnumerable<T> input) {
03            var count = input.Count();
04            return count == input.Distinct().Count();
05        }
06    }

When you want to test an IEnumerable<T>,  just write

07 var isAPotentialPrimaryKey=CandidateColumn.AllDistinct();

Analysis

This solution is simple and probably scales as well as any solution in the worst case.  However,  it enumerates the IEnumerable<T> twice and does a full scan of the IEnumerable even if non-distinct elements are discovered early in the enumeration.  I could certainly make an implementation that aborts early using a Dictionary<T,bool> to store elements we’ve seen and a foreach loop,  but I wonder if anyone out there can think of a better pure-Linq solution.

]]>
http://gen5.info/q/2009/02/13/using-linq-to-tell-if-the-elements-of-an-ienumerable-are-distinct/feed/ 1

Warning: fsockopen(): php_network_getaddresses: getaddrinfo failed: No address associated with hostname in /hosting/sites/gen5.info/htdocs/q/wp-includes/class-snoopy.php on line 1148

Warning: fsockopen(): unable to connect to :80 (php_network_getaddresses: getaddrinfo failed: No address associated with hostname) in /hosting/sites/gen5.info/htdocs/q/wp-includes/class-snoopy.php on line 1148