The Future of C#

One of the future additions to C# announced by Anders Hejlsberg in this entertaining video from 2008 is Compiler as a Service. By that he means the ability to eval code strings (and I'm guessing that this will also be integrated with C#'s built-in AST objects).

He shows this off at around minute 59, to great effect and great excitement by the audience. It feels like an inflection point. There probably won't be another REPL-less language from now on.

I predict that after that, they'll add hygienic macros and quasisyntax.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I predict that after that,

I predict that after that, they'll add hygienic macros and quasisyntax.

A guy I know likes to joke, "Nemerle: C# 5.0, Today!" Which is not really too far from the truth.

Also, Mono had compiler as a service implemented before MSFT. So credit goes to the Mono guys, not Anders Hejlsberg and his design team. The way Mono also exposed this was fairly elegant, as they used the Mono Linker framework to simply hide everything except for four methods from the public API.

except

that the C# web site doesn't disappear off of the network on a regular basis, etc. etc. :-}

Insert standard "reinventing Lisp" observation, here.

As always - a solid, positive step - if not exactly a new notion.

Hm...

I think that C# is the first "dynamic" language that actually moves forward from Lisp – C#'s dynamic types bring Lisp's untyped programming style into a statically typed language. I'm not aware of any Lisp that has that property (of being able to switch between typed and untyped), except maybe very new languages such as Typed Scheme.

[Update: Yes, the use of a REPL in mainstream PLs is due for at least 50 years now, but I think C# is one of the few dynamic languages that actually progress beyond plain Lisp.]

nope

C# is not at all the first language with mixed typing. It's not even the first OO language. For something very similar to C#'s "dynamic" type see Boo and for an alternative where the message send operator determines static vs dynamic see Fantom.

Mixed static and dynamic typing has been discussed before on LtU, and likely in many other contexts.

Even in the commercial

Even in the commercial space, ActionScript 3 has it beat. (Maybe even VB? Not as familiar.)

What does 'has it beat' mean?

C# dynamic has some strengths, weaknesses and corner cases, but it is also a different way to approach problems. The specification for it has also changed drastically since PDC 2008. It is confusing what you can do with "dynamic" at this point, and since I haven't had a real need to use it, I stay away from it, since I avoid features of a language that I don't understand how to use correctly. To me, I should be able to look at code and read it and understand what it does.

I also think you are missing the point. C# is not trying to beat ActionScript 3 or whoever or be the best in the commercial space at dynamic typing. Instead, it is trying to improve interoperability with the languages that are trying to be the best at dynamic typing. The key question is whether C# chose the best way, from the perspective of a statically typed language. And if not, have they hindered the possibility for improving interpoerability with dynamic languages in the future.

What's your framework for comparison? What criteria are you setting that defines what 'has it beat' mean?

"beat"

I think "has it beat" was just supposed to mean that ActionScript 3 came before C# dynamic (contrary to the previous comment which seemed to say C# was the "first language" with this ability).

Beat in a temporal sense,

Beat in a temporal sense, not in an atemporal one like quality.

The last time I used AS (in 'anger', as Wadler would say), it had a Java (pre-generics) feeling, which is pretty much not what I want in a language for massaging media. I haven't tried to track down why, but others have noticed a similar phenomena: the incorporation of types in a snippet quickly bleeds outside of the snippet, so a surprising amount of AS3 onwards skips the dynamic typing tradition of the family. Understanding why would be fascinating. AS3 is actually a pretty great language -- a lot of what is missing in JavaScript is here (e.g., weak references). The type & OO system seemed like a dual-purpose hammer for transitioning enterprise developers and enabling better performance: the former seems antiquated and TJITs suggest the latter is unnecessary.

My experiences with C# are pretty much nil -- for a language on that level, I worked more on the Java side. Obviously, times have changed (local type inference, etc.) but I haven't had a project suggesting its use yet.

Even in the commercial

Even in the commercial space, ActionScript 3 has it beat.

I've had to do some Flex programming for work lately, every time I use actionscript I feel like I'm getting the worst of two typing worlds. It is difficult at best to utilize the type annotations enough to provide you with any of the benefits of having a type system in the first place. I hope it can be done much better.

(Maybe even VB? Not as familiar.)

A paper referenced elsewhere in this thread talks about this aspect of VB a bit. I haven't used it myself though and cannot compare.

Not really dynamic...

I don't think it's fair to actually call C# dynamic. It can consume objects dynamically (late binding) and also it can interop with nicely with dynamic objects from dynamic runtimes (DLR/COM) but I think a core aspect of actually being dynamic is the ability to change your own Type metadata. That is still static.

I think what you get in C# 4 is duck typing, technically. The feature set is identical to Boo. Also, actually, the compiler as a service feature is identical to boo also. Next thing you know you'll get pattern matching also...

Technically, no.

I think what you get in C# 4 is duck typing, technically.

Ducktyping is just allowing the caller to supply a record of functions the object should respond to. In statically typed object-oriented languages, we don't pretend an object has an interface it doesn't. Instead, we refactor our applications to add more static structure. The advantages are:

(1) Improved static analysis, such as automated code review by a tool that checks for best practices, e.g., pulling a snippet of code I found off StackOverflow thread c# 4 dynamic keyword - why not?:

public T Foo(T other) where T: ICloneable, IAssignData{
    T clone = (T)other.Clone();
    clone.AssignData(this.Data);
    return clone;
}

Here, we can set-up FxCop and Mono.Gendarme to flag any generic method with a type constraint that uses ICloneable. I suppose you could do the same thing using a dynamically typed language with duck typing, but the static analysis will never be as good. Since the Framework Design Guidelines say not to use ICloneable, we really want FxCop and Gendarme rules to flag proliferation of it.

(2) Changing the static structure of any system should set off warning bells to the system designer that the requirements should be revisited. For example, allowing cloning opens the door to breaking invariants. Adding a cloning function to an object's interface requires complete reconsideration of the object by its designer, especially the scenarios for which the object's collaborating classes use it. If you haven't thought through your scenarios at this point, of course trying to analyze the impact of static structural changes will be painful if not ignored entirely.

(3) Duck typing generally is just syntactic sugar for hardwiring sequences of collaborations among potentially disparate objects. Since we want to resist adding unnecessary dependencies to our applications, hardwiring the orders in which objects invoke one another is probably a bad idea. Among reasons, it is definitely a modularity problem.

(4) Calling it ducktyping is a strawman argument for wanting C# to actually support ducktyping, which, for reasons I've mentioned above, probably shouldn't be supported. Omer van Kloeten argued this erroneous opinion, which amounts to ducktyping via caller-side interface injection. I don't like caller-side interface injection because of my belief that ducktyping hardwires sequences of collaborations using out-of-band communication. How long does the side effect of interface injection last for? If it escapes lexical scope, then we're violating law of demeter. We know we can have super and inner together at last - why decide something structurally inferior? Macros would be superior for hardwiring sequences of collaborations, since they would be more general and more closely approximate what the programmer is actually trying to achieve in a statically typed system.

Technically yes

Duck typing is just allowing the caller to supply a record of functions the object should respond to. In statically typed object-oriented languages, we don't pretend an object has an interface it doesn't. Instead, we re-factor our applications to add more static structure.

I agree with the sentiment that it _shouldn't_ be supported, but C#s dynamic keyword does introduce duck typing. I think on LtU people can appreciate that the implementation mechanism (dictionary of functions vs reflection) is irrelevant, the semantics are the same from the users point of view.


public T Foo(T other) where T: ICloneable, IAssignData{
    T clone = (T)other.Clone();
    clone.AssignData(this.Data);
    return clone;
}

It is surprising that this was chosen as an example of good code compared to it's "dynamic" equivalent. I would have used an example that was actually type-safe personally...

Calling it ducktyping is a strawman argument for wanting C# to actually support ducktyping, which, for reasons I've mentioned above, probably shouldn't be supported. Omer van Kloeten argued this erroneous opinion, which amounts to ducktyping via caller-side interface injection.

What part of his argument is erroneous, or do you just disagree? In which case it is misleading to call it erroneous, implying some sort of factual error.

I agree with the sentiment

I agree with the sentiment that it _shouldn't_ be supported, but C#s dynamic keyword does introduce duck typing.

I spot-checked the definition of duck typing in multiple places, and it looks like you and Justin are both right and I'm wrong. Thinking it over, my definition doesn't even make sense in the context of dynamic languages.

It is surprising that this was chosen as an example of good code compared to it's "dynamic" equivalent. I would have used an example that was actually type-safe personally...

I think you missed the part where I said a good set of automated code review rules would disallow this code. I don't recommend implementing ICloneable, or even using it even if ICloneable is supported. Cloning in general is bad because it breaks variants. Referential integrity problems are the worst kinds of problems to debug. (Instead, prefer a Memento pattern where you model the dependency explicitly, and use multiple Mementos if you have multiple contexts to reflect changes to; this will generally be thread-safe.) I was just trying to illustrate how static typing brings bad design to the surface via automated code review tools, especially in a larger project.

What part of his argument is erroneous, or do you just disagree? In which case it is misleading to call it erroneous, implying some sort of factual error.

He wants the dynamic keyword to support IntelliSense, which is the gist of his gripe: the dynamic keyword does not force the programmer to document what features of an object the programmer wants to use. Sorry, but if you're using dynamic in this way, you are not . In C#, you're better off getting a static type from a proxy factory. Interestingly, I just googled to see if something similar to the Apache Commons ProxyFactory exists in .NET. Funny enough, .NET has a library that does this and it is called the DuckTyping Project.

The whole point of the dynamic keyword is to indicate dynamic dispatch. There is nothing "dynamic" about what Omer wants, so it doesn't make sense to annotate it as such. "dynamic" compiles down to "[DynamicAttribute] object" What he wants is caller-side (static) structural typing. You could achieve this with hygienic macros.

Inflection point ?

What's one of them ? Maybe a point of intonation ? It's depressing to see linguistic terms misused on a programming languages web site.

It's a basic calculus term.

It's a basic calculus term. "In differential calculus, an inflection point, point of inflection, or inflection (inflexion) is a point on a curve at which the curvature (second derivative) changes signs." (Wikipedia; also the definition I've been using since my first calculus course, at least)

Turning this ship around...

And in this case, used metaphorically to indicate a subtle but important turning point. It's a very evocative metaphor, actually. I don't know of another phrase for this notion that has such a clear visual intuition.

Terminology has context

Inflection point: "n. A moment of dramatic change, especially in the development of a company, industry, or market."

Except in this case, I think it's more likely a case of conference fever. :)

When discussing the future

When discussing the future of C#, it is also worth looking at the recent developments and research involving the F# language. It seems that many of the C# features come from F# and people involved in F# (Don Syme and Andrew Kennedy) already largely contributed to things like C# generics. (Of course, many of the ideas in F# are inspired by other existing non-Microsoft research work, but F# is in the same "product group" as C#, so this is probably the shortest path for transfering research ideas into C#).

Anyway, I wouldn't be surprised if some of the successful ideas from F# served as an inspiration to the C# team... we'll see :-)

How much is F# influenced by

How much is F# influenced by Haskell and the work MS Research has done? I have no doubt that LINQ was heavily influenced by Haskell's use of monads.

LINQ and Haskell

I don't know enough about F# and Haskell to really answer this, but there's definitely some influence. For example, the design of F#'s computation expressions is acknowledged to be based on Haskell's monads. In fact, one of the reasons they chose to call it "workflows" rather than "monads" because they were discussing the feature with the designers of Haskell, and they felt that the term "monad" was a bit, quote, 'obscure and daunting' (sc. for F#'s target audience).

And you're absolutely right about LINQ: one of the architects of LINQ was Erik Meijer, who came from a Haskell background. There's a paper of Meijer's, "Confessions of a Used Programming Language Salesman," which describes the development of the ideas that became LINQ from Haskell through to C# and Visual Basic.

Confessions of a Used Programming Language Salesman

CLR 5.0?

I would think that the biggest improvements F# could offer would be tighter integration with other .NET languages. In this way, I would expect at some point another major version release of the Common Language Runtime. It has been half a decade since the last major drop (i.e., a change to the CIL and assembly metadata portions of Ecma-335).

In particular, currently the F# compiler erases some F#-specific type annotations like units of measure. That means the .NET assembly has no knowledge of units of measure. Since Andrew Kennedy did his Ph.D. thesis on units of measure and was the principal investigator/programmer into how F# would support this feature, and also one of the co-designers of the CLR 2.0 Generics system, it stands to reason that at some point Kennedy will return to CLR-related work and improve the runtime.

Besides that low-hanging fruit, the F# language is about making ML-style programming more widely accessible. That means that Luke Hoban will be listening to community feedback, and if somebody like Kalani Thielen campaigns for type classes-like functionality and can demonstrate to the F# target audience why it would be a boost to their productivity.

Some potential future features for F# and the CLR lie at an intersection between sharing code (using generics) and good performance. For example, the CLR JIT compiler currently cannot outperform hand-written manual ad-hoc implementations of something like Sum. I would suspect this has to be addressed first before Don and Andrew consider adding such features to F#, but I would be interested to hear what they think.

Another point: Luke Hoban has stated that F# is the sort of MSFT language that should go through revisions every one or two years, closer to the VB.NET and C# release cycles. Longer release cycles are actually a good thing, because it means MSFT is committed to integration with all of its other tools, such as Visual Studio Team System. By contrast, fringe languages like IronPython (Jim Hugunin) and IronRuby (John Lam) have very agile release cycles and folks can just grab the latest bits whenever they please, and since the languages are mostly re-implementations, most people using IronPython and IronRuby test in multiple environments, e.g. IronRuby, MacRuby, JRuby, to ensure their unit tests pass on all systems -- that's just good engineering.

With F#, again, it is different from IronRuby. More emphasis should go into .NET libraries for the language rather than strict Ocaml ports. Eventually, F# needs to create its own identity.

When will F# get type classes?

It would be very useful to have multi-parameter type classes (plus functional dependencies) and higher-kinded types.

Speculation

See this video from Microsoft PDC 2009 where Luca Bolognese speculates on and demonstrates a possible new concurrency construct for C# 5:

Future Directions for C# and Visual Basic

Lisa Feigenbaum on C# future

Q&A: Microsoft's Lisa Feigenbaum Talks about C# 4 (I've added some links to postings by MSFT employees who have worked on the C# design team.)

MD: Counterpoint: What feature or features are C# users requesting most?

LF: Given the number of C# developers, you can imagine that we receive an enormous number of requests! I'll share a few of the most popular ones: tuples, immutable types, non-nullable types, a null propagating member access operator, an "infoof" operator, XML literals, arithmetic constraints on generics, and extension everything (properties, events, etc.).

While we have hundreds of feature requests, it's interesting to note that we actually wouldn't want to program in a language that had all of the features we want in it -- it would be too complex! Figuring out which subset of features to include is part of the art of language design.

Generic numerics are a feature people have wanted from the CLR for awhile.

MD: In C# 3.x, IEnumerable didn't get a "ForEach" method. In C# 4.0, it still doesn't have ForEach. It's probably one of the most common extension methods written by developers. Why do we still not have a ForEach (Action) on IEnumerable?

LF: The C# 3 LINQ sequence operators follow functional programming paradigms, avoiding state and mutable data. However, ForEach doesn't return any values, so it would only be used to produce side effects. This conflicts with the functional design principles for sequence operators, and is one of the key reasons why it was not introduced.

Fortunately, if you'd like to proceed with this approach anyway, it is just a one-line extension method that you have to write.

Lisa overlooks the fact the .NET Rx team is providing Do and Run side-effect operations, but her point remains: IEnumerable extension methods are designed to be immutable.