0% found this document useful (0 votes)
39 views11 pages

SynapseIndia Feedback On Dotnet Development and C# Versions

This document discusses features of C# 3.0 that make it more functional, including generics, delegates, lambda expressions, type inference, and LINQ methods. It compares C# to ML and Haskell and how C# 3.0 narrowed the gap between them with these additions.

Uploaded by

synapseindia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views11 pages

SynapseIndia Feedback On Dotnet Development and C# Versions

This document discusses features of C# 3.0 that make it more functional, including generics, delegates, lambda expressions, type inference, and LINQ methods. It compares C# to ML and Haskell and how C# 3.0 narrowed the gap between them with these additions.

Uploaded by

synapseindia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 11

SynapseIndia Feedback on

Dotnet Development and C#


Versions

Quicksort revisited

Name the language...

C#
3.0

parameterized type of
functions
Func<intlist, intlist> Sort = higher-order
xs =>
function
lambda
xs.Case(
expression
() => xs,
(head,tail) => (Sort(tail.Where(x => x < head)))
.Concat
(Single(head))
append
type
.Concat
inference
(Sort(tail.Where(x => x >= head)))
);
recursio
n

filter

The gap narrows...

C# 3.0 has many features well-known to functional


programmers
Parameterized types and polymorphic functions (generics)
First-class functions (delegates)
Lightweight lambda expressions & closure conversion
Type inference (for locals and lambdas)
Streams (iterators)
A library of higher-order functions for collections & iterators
And even: GADTs (polymorphic inheritance)

This talk: is it serious competition for ML and Haskell?


(Note: Java 5 has many but not all of the above features)

A brief history of fun in C#

C# 1.0:
First-class functions (delegates), created only from
named methods. Environment=object, code=method.

C# 2.0:
Parameterized types and polymorphic methods
(generics)
Anonymous methods: creation of delegate objects from
code bodies, closure-converted by C# compiler
Iterators: stream abstraction, like generators from Clu

C# 3.0:
Lambda expressions: lightweight syntax for anonymous
methods whose bodies are expressions
Type inference for locals and lambdas
(Also, not discussed: expression trees for lambdas)

Delegates (C# 1.0)

Essentially named function types e.g.


delegate bool IntPred(int x);

Delegate objects capture a method code pointer together


with an object reference e.g.
class Point {
int x; int y;
bool Above(int ybound)
{ return y >= ybound; }
}
Point point;
IntPred predicate = new IntPred(point.Above);

Compare (environment, code pointer) closure in a


functional language.

Generics (C# 2.0)

Types (classes, interfaces, structs and delegates) can be


parameterized on other types e.g.
delegate R Func<A,R>(A arg);
class List<T> { ... }
class Dict<K,D> { ... }

Methods (instance and static) can be parameterized on


types e.g.
static void Sort<T>(T[] arr);
static void Swap<T>(ref T x, ref T y);
class List<T> {
List<Pair<T,U>> Zip<U>(List<U> other) ..

Very few restrictions:

Parameterization over primitive types, reference types, structs

Types preserved at runtime, in spirit of the .NET object model

Generics: expressiveness
1.

Polymorphic recursion e.g.


static void Foo<T>(List<T> xs) {
Foo<List<List<T>>>() }

2.

First-class polymorphism (System F) e.g.


interface Sorter { void Sort<T>(T[] arr); }
class QuickSort : Sorter { }
class MergeSort : Sorter { }

3.

GADTs e.g.
abstract class Expr<T> { T Eval(); }
Also possible
class Lit : Expr<int> { int Eval() { } }
in Java 5
class PairExpr<A,B> : Expr<Pair<A,B>>
{ Expr<A> e1; Expr<B> e2; Pair<A,B> Eval() { } }

Anonymous methods (C# 2.0)

Delegates are clumsy: programmer has to name the function


and closure-convert by hand
So C# 2.0 introduced anonymous methods
No name
Compiler does closure-conversion, creating a class and object
that captures the environment e.g.
bool b = xs.Exists(delegate(int x) { return x>y; });
Local y is free in body of
anonymous method

IEnumerable<T>

Like Java, C# provides interfaces that abstract the ability to


enumerate a collection:
interface IEnumerable<T>
{ IEnumerator<T> GetEnumerator(); }
interface IEnumerator<T> {
T Current { get; }
bool MoveNext();
}

To consume an enumerable collection, we can use the


foreach construct:
foreach (int x in xs) { Console.WriteLine(x); }

But in C# 1.0, implementing the producer side was errorprone (must implement Current and MoveNext methods)

Iterators (C# 2.0)

C# 2.0 introduces iterators, easing task of implementing


IEnumerable e.g.
static IEnumerable<int> UpAndDown(int bottom, int top) {
for (int i = bottom; i < top; i++) { yield return i; }
for (int j = top; j >= bottom; j--) { yield return j; }
}

Iterators can mimic functional-style streams. They can be


infinite:
static IEnumerable<int> Evens() {
for (int i = 0; true; i += 2) { yield return i; } }

The System.Query library provides higher-order functions on


IEnumerable<T> for map, filter, fold, append, drop, take, etc.
static IEnumerable<T> Drop(IEnumerable<T> xs, int n) {
foreach(T x in xs) { if (n>0) n--; else yield return x; }}

Lambda expressions

Anonymous methods are just a little too heavy compared


with lambdas in Haskell or ML: compare
delegate (int x, int y) { return x*x + y*y; }
\(x,y) -> x*x + y*y
fn (x,y) => x*x + y*y

C# 3.0 introduces lambda expressions with a lighter syntax,


inference (sometimes) of argument types, and expression
bodies:
(x,y) => x*x + y*y
Language specification simply defines lambdas by
translation to anonymous methods.

You might also like