Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# lambda expressions and lazy evaluation

One advantage of lambda expressions is that you have to evaluate a function only when you need its result.

In the following (simple) example, the text function is only evaluated when a writer is present:

public static void PrintLine(Func<string> text, TextWriter writer)
{
    if (writer != null)
    {
        writer.WriteLine(text());
    }
}

Unfortunately, this makes using the code a little bit ugly. You cannot call it with a constant or variable like

PrintLine("Some text", Console.Out);

and have to call it this way:

PrintLine(() => "Some text", Console.Out);

The compiler is not able to "infer" a parameterless function from the passed constant. Are there any plans to improve this in future versions of C# or am I missing something?

UPDATE:

I just found a dirty hack myself:

    public class F<T>
    {
       private readonly T value;
       private readonly Func<T> func;

       public F(T value) { this.value = value; }
       public F(Func<T> func) {this.func = func; }

       public static implicit operator F<T>(T value)
       {
            return new F<T>(value);
       }

       public static implicit operator F<T>(Func<T> func)
       {
           return new F<T>(func);
       }

       public T Eval()
       {
           return this.func != null ? this.func() : this.value;
       }
}

Now i can just define the function as:

public static void PrintLine(F<string> text, TextWriter writer)
{
    if (writer != null)
    {
        writer.WriteLine(text.Eval());
    }
}

and call it both with a function or a value.

like image 333
Rauhotz Avatar asked Jan 05 '09 19:01

Rauhotz


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.


2 Answers

I doubt that C# will get this feature, but D has it. What you've outlined is a suitable way to implement lazy argument evaluation in C#, and probably compiles very similarly to lazy in D, and in more pure functional languages.

All things considered, the four extra characters, plus optional white space, are not an exceptionally large price to pay for clear overload resolution and expressiveness in what is becoming a multi-paradigm strong-typed language.

like image 145
P Daddy Avatar answered Oct 06 '22 09:10

P Daddy


The compiler is very good at inferring types, it is not good at inferring intent. One of the tricky things about all the new syntactic sugar in C# 3 is that they can lead to confusion as to what exactly the compiler does with them.

Consider your example:

() => "SomeText"

The compiler sees this and understands that you intend to create an anonymous function that takes no parameters and returns a type of System.String. This is all inferred from the lambda expression you gave it. In reality your lambda gets compiled to this:

delegate {
    return "SomeText";
};

and it is a delegate to this anonymous function that you are sending to PrintLine for execution.

It has always been important in the past but now with LINQ, lambdas, iterator blocks, automatically implemented properties, among other things it is of the utmost importance to use a tool like .NET Reflector to take a look at your code after it is compiled to see what really makes those features work.

like image 41
Andrew Hare Avatar answered Oct 06 '22 08:10

Andrew Hare