Being a language fanatic, I was really excited when I met a really smart guy named Corey Kosak who gave me a tour of C#'s newest features. I had heard a lot of good things about C# lately, including that it had been strongly influenced by Haskell, which makes sense since Microsoft actually funds research on Haskell. Anyway, a lot of C#'s newest features are a lot more like Python than Java. Let me show you some examples.
Here is a sample C# iterator:
C# also iterators that are similar to Python's generators. Here is the C#:
C#'s LINQ syntax is similar to Python's generator expressions. Here's the C#:
Here's a pretty amazing example that ties a lot of things together. It shows LINQ, a "group by" clause, an anonymous but strongly-typed class ("new {...}"), and even some type inferencing ("var item" and "item.FirstChar")
"Loosely translated", in Python I'd write:
C#'s Select method can be used like map in Python. Notice the use of an anonymous function!
The above example can also be written in LINQ style:
If you don't want newInts to be lazy, you can do:
Since C# has anonymous functions, it should come as no surprise that it also has nested scopes and first-class functions (i.e. you can return a function). Although you can't nest named functions, it's easy enough to fake with anonymous functions:
C# also has closures:
C#'s generics are a bit more powerful than Java's generics since they don't suffer from erasure. I can't say I'm an expert on the subject. Nonetheless, I'm pretty sure you can't easily translate this example into Java. It creates a new instance of the same class as the instance that was passed as a parameter:
Python has duck typing, so it doesn't have or need generics. Here's what I would write in Python:
Unfortunately, those are all the examples I have, but let me mention a few other things he showed me.
C# has a method called Aggregate that is the same as what other languages called inject or reduce.
C# has Lisp-like macros! You can pass an AST (abstract syntax tree) around, play with it, and then compile it at runtime.
C# has an interesting feature called "extension methods". They're somewhat like a mixin or reopening a class in Ruby. Using an extension method, you can set things up so that you can write "5.Minutes()". Unlike a mixin or reopening a class, they're pure syntax and do not actually affect the class. Hence, the above translates to something like "SomeClass.Minutes(5)". Although "5" looks like the object being acted upon, it's really just a parameter to a static method.
Another thing that impressed me was just how hard Visual Studio works to keep your whitespace neat. It doesn't just indent your code. It also adds whitespace within your expressions.
Ok, that's it. As usual, I hope you've enjoyed a look at another language. I'd like to thank Corey Kosak for sending me the C# code. If I've gotten anything wrong, please do not be offended, just post a correction in the comments.
Here is a sample C# iterator:
foreach(var x in CountForeverFrom(123).Take(5)) {In Python, I'd write:
Console.WriteLine(x);
}
for i in itertools.islice(itertools.count(123), 5):
print i
C# also iterators that are similar to Python's generators. Here is the C#:
public static IEnumerable<int> CountForeverFrom(int start) {In Python, I'd write:
while(true) {
yield return start;
start++;
}
}
def count_forever_from(start):
while True:
yield start
start += 1
C#'s LINQ syntax is similar to Python's generator expressions. Here's the C#:
var names=new[] { "bill", "bob", "tim", "tom", "corey",In Python, I'd write:
"carl", "jj", "sophie" };
foreach(var x in (from name in names where name.Length>5 select name)) {
Console.WriteLine(x);
}
names = ["bill", "bob", "tim", "tom", "corey", "carl", "jj", "sophie"]
for x in (name for name in names if len(name) > 5):
print x
Here's a pretty amazing example that ties a lot of things together. It shows LINQ, a "group by" clause, an anonymous but strongly-typed class ("new {...}"), and even some type inferencing ("var item" and "item.FirstChar")
var crap=from n in namesCorey said that C#'s type inferencing is still pretty basic. It can figure out the type of a local variable, but it's definitely not as sophisticated as ML's type system. Also note that the anonymous class is more impressive that an inner class in Java because it didn't require you to use a name or an interface.
group n by n[0]
into g
select new { FirstChar=g.Key,
Data=(from x in g select x).ToArray() };
foreach(var item in crap) {
Console.WriteLine(
"First group is {0} which has length {1}. The contents are:",
item.FirstChar, item.Data.Length);
foreach(var x in item.Data) {
Console.WriteLine(x);
}
}
"Loosely translated", in Python I'd write:
crap = itertools.groupby(names, lambda n: n[0])
for first_char, subiter in crap:
group = list(subiter)
print "Group is %s which has length %s. The contents are:\n%s" % (
first_char, len(group), "\n".join(group))
C#'s Select method can be used like map in Python. Notice the use of an anonymous function!
var newInts=ints.Select(x => x*x);In Python, I'd write:
new_ints = map(lambda x: x * x, ints)The C# version runs lazily (i.e. "on the fly"), which means it only computes as much as requested. Python's map function isn't lazy. However, itertools.imap is.
The above example can also be written in LINQ style:
var newInts2=(from temp in ints select temp*temp);In Python I'd write:
new_ints2 = (temp * temp for temp in ints)Both the C# and the Python are lazy in this case.
If you don't want newInts to be lazy, you can do:
var intArray=newInts.ToArray();or
var intList=new List<int>(newInts);In Python, I'd write:
list(new_ints)
Since C# has anonymous functions, it should come as no surprise that it also has nested scopes and first-class functions (i.e. you can return a function). Although you can't nest named functions, it's easy enough to fake with anonymous functions:
private static Action<int> NestedFunctions() {In Python, I'd write:
int x=5;
Action<int> addToX=newValue => {
x+=newValue;
};
addToX(34);
addToX(57);
Console.WriteLine(x);
return addToX;
}
def nested_functions():
def add_to_x(new_value):
add_to_x.x += new_value
add_to_x.x = 5
add_to_x(34)
add_to_x(57)
print add_to_x.x
return add_to_x
C# also has closures:
private static void BetterExampleOfClosures() {Python has closures too. (There's a small caveat here. You can modify a variable that's in an outer scope, but there's no syntax for rebinding that variable. Python 3000 fixes this with the introduction of a nonlocal keyword. In the meantime, it's trivial to work around this problem.):
var a=MakeAction(5);
a();
a();
a();
}
private static Action MakeAction(int x) {
return () => Console.WriteLine(x++);
}
def better_example_of_closures():
a = make_action(5)
a()
a()
a()
def make_action(x):
def action():
print action.x
action.x += 1
action.x = x
return action
C#'s generics are a bit more powerful than Java's generics since they don't suffer from erasure. I can't say I'm an expert on the subject. Nonetheless, I'm pretty sure you can't easily translate this example into Java. It creates a new instance of the same class as the instance that was passed as a parameter:
public abstract class Animal {Corey told me that while C#'s generics are stronger than Java's generics, they still weren't as strong as C++'s generics since C++ generics act in an almost macro-like way.
public abstract void Eat();
}
public class Cow : Animal {
public override void Eat() {
}
}
public class Horse : Animal {
public override void Eat() {
}
}
public static T Func<T>(T a, List<T> list) where T : Animal, new() {
return new T();
}
Python has duck typing, so it doesn't have or need generics. Here's what I would write in Python:
class Animal():
def eat(self):
raise NotImplementedError
class Cow():
def eat(self):
pass
class Horse():
def eat(self):
pass
def func(a, list_of_a):
return a.__class__()
Unfortunately, those are all the examples I have, but let me mention a few other things he showed me.
C# has a method called Aggregate that is the same as what other languages called inject or reduce.
C# has Lisp-like macros! You can pass an AST (abstract syntax tree) around, play with it, and then compile it at runtime.
C# has an interesting feature called "extension methods". They're somewhat like a mixin or reopening a class in Ruby. Using an extension method, you can set things up so that you can write "5.Minutes()". Unlike a mixin or reopening a class, they're pure syntax and do not actually affect the class. Hence, the above translates to something like "SomeClass.Minutes(5)". Although "5" looks like the object being acted upon, it's really just a parameter to a static method.
Another thing that impressed me was just how hard Visual Studio works to keep your whitespace neat. It doesn't just indent your code. It also adds whitespace within your expressions.
Ok, that's it. As usual, I hope you've enjoyed a look at another language. I'd like to thank Corey Kosak for sending me the C# code. If I've gotten anything wrong, please do not be offended, just post a correction in the comments.
Comments
Technically speaking, C# calls them iterators: http://msdn.microsoft.com/en-us/library/dscyy5s0.aspx
Yes, actually.
JJ and I were too busy playing Katamari for me to mention that... :-)
It's crazy!!! You need to write:
for i in xrange(123, 128):
Python is much better!
Naturally, I'm a huge fan of Python too.
I'm sorry, I wasn't being very clear. I was just trying to show that you can slice and dice iterators. In real code, you should definitely use xrange as you showed. You use islice when you have some other iterator that you need to take a slice of.