Eric Rambles On About C#, Again

Eric Rambles On About C#, Again

Rate This
  • Comments 8

Rachel Roumeliotis, who amongst other things edits C# books for O'Reilly, recently did an interview with me where I ramble on about async/await, Roslyn, performance analysis as an engineering discipline, and some broad-strokes ideas for future language research areas. If you have sixteen minutes to burn, check it out! The O'Reilly Radar blog post is here, and the video has also been posted to YouTube here.

A couple things to mention here; first, I say in the video that we've shipped one preview release of Roslyn; in fact we have shipped two. The video was recorded before we had announced the new release. And second, I want to re-emphasize that the end bit where you get more of Eric's musings about ideas for future language research areas are for your entertainment. We have not announced any product beyond Roslyn, and we are certainly making no promises whatsoever about the feature sets of unannounced, entirely hypothetical products. Enjoy!

  • I always enjoy hearing about what features you're *thinking about*, even if it's not likely to end up in C#. I've been trying to find the time for my own language for a while (I've written a bunch of front-ends, and a few simple codegen/interpreter pairs for different projects, I just need to put them together some time), so hearing about your crazy ideas is great motivation!

    PS: Phew! I was worried the purple text was a casualty of the redesign!

  • Interesting! Good talk :)

    One thing that I always see as a limit in Visual Studio is the ability to write complex statements/expressions in the Watch or the Immediate Window while debugging, such as LINQ queries or lambda expressions. I can understand the reasons behind that, considering the complex compiler magic that's behind both of those things (and other things that are limited there, like array type inference and property initializers) but the ability to do so would be worth a Visual Studio upgrade just for that for me. And I was wondering: is that something that Roslyn will make possible/easier to implement?

  • I'd love to see more immutable programming structures that are more friendly to a functional style of programming.  There's a lot of really cool features in F# that I'd love to see make their way into C# (record types, discriminated unions, pattern matching, object expressions [this would be amazing for unit testing]) and other features from languages like Scala (traits, immutable variables) that I'd also love to see added.

    Of course there's always the usual things I'd love to see to help better protect against NullReferenceException like the safe access operator that would get rid of all of those if(blah == null) checks before accessing a member of blah.

  • Eric rambles on? I'll show you rambling :)

    I'm glad you mentioned metaprogramming (and, sure, functional programming) as possible future directions for C#. I'm considering a change from C# to D as my primary language because of (1) its metaprogramming capabilities and (2) its efficiency advantage over .NET, which is partly the result of its metaprogramming abilities (I'm convinced .NET could and should be faster, but I digress.) -- though if I do switch languages I will definitely miss some of .NET, like runtime codegen and dynamic linking features and some of the BCL. Metaprogramming is the cornerstone of my pet compiler project that I never had time to actually do.

    When trying to design metaprogramming features, I would suggest keeping in mind a series of use cases... and then implementing a working sketch of each, to make sure your proposed features work well. So allow me to suggest some things to do with metaprogramming:

    1. Numeric algorithms that operate on a wide range of numeric data types efficiently. I rely on this in C++ all the time; I target CPUs without floating-point units and so it's extremely useful to be able to use the same algorithms in integer fixed-point or floating-point. Some research was done on using .NET generics for this, but it is cumbersome in C# and my benchmarks show a significant performance penalty for using .NET generics instead of code that is hard-coded for doubles/ints/etc.

    2. Building look-up tables at compile-time.

    3. Running parser-generators at compile-time (without the hassle of a separate code generator).

    4. And of course, other kinds of DSLs.

    5. Traits: the user writes "trait" classes that exist only at compile-time, then a metaprogram is used to compose them into a single class.

    6. Code contracts (solved problem? okay, but given good metaprogramming facilities, mere mortals could implement this kind of feature).

    7. Shortcuts: metaprograms could make all sorts of code shorter. For instance I am absolutely sick to death of writing constructors of the form "public Foo(Bar bar, Wunderbar wunderbar) { _bar = bar; _wunderbar = wunderbar; }" and I imagine a metaprogram that lets me write simply "public Foo(init _bar, init _wunderbar) {}" (bonus points if the metaprogram can rename the constructor parameters to "bar" and "baz" for convenient use as named parameters).

    8. Easy decorators. In the decorator pattern, the user writes a series of wrapper methods. Often, many of the wrapper methods just call the underlying methods; a metaprogram could generate such wrappers automatically.

    9. Propagating variables (a personal favorite). I believe that eventually, a system of automatic change propagation will be a standard feature used in GUI programming (and maybe other domains). The gist of it: a metaprogram figures out the dependencies in your code and implements INotifyPropertyChanged for you. It could (and should) get fancier, but that's the basic idea. There's a library called UpdateControls which, impressively, does something like this at runtime, but compile-time approaches could be more efficient and reliable.

    10. Unit inference. A program would specify units on some fields, parameters and expressions (e.g. bytes, words, pixels, ms, seconds, pixels per second, relative or absolute coordinates, X/Y axis, etc.); then a metaprogram would infer the units of all other symbols in the program, and detect inconsistencies (such as trying to add screen pixels to WPF density-independent pixels). I have some experience here, having written a unit-inference engine for boo. The common approach to unit checking, of having data types like Metre<int> and Seconds<double>, is a huge PITA, does not scale, and (in .NET) would harm performance; a proper solution computes units in a parallel type system that does not affect the compiler output at all (except, of course, if the user wants runtime unit checking).

    11. Aspect-oriented programming

    12. Code optimization and analysis. The metaprogram optimizes function bodies or detects potential errors. For example, one could write a compile-time inliner (does the official compiler do any inlining whatsoever at compile-time? it would be a useful thing to have, since the JIT is nowhere near as good at inlining as C++)

    13. Covariant return types when overriding. I know .NET steadfastly refuses to support this, but somebody could write a metaprogram to fake it through auto-transformation.

    14. Compile-time unit testing (bonus points if a user can write unit tests right beside the code being tested, and then a compiler plugin lifts the tests out into a separate DLL)

    15. Compile-time equation solving: solve_for(x, x^2 - 2*x + y = 0)

    16. Go-style interfaces and/or VB-style dynamic interfaces.

    17. Give me some time, I can think of more :)

    A solid metaprogramming system is awesome because it lets the users define new language features.

    Assembly weaving, Roslyn, and T4 templates could already be used for some (but by no means all) of these features, and with caveats compared to a proper metaprogramming system. e.g.: It's non-obvious how to install a weaver in a Visual Studio project. Roslyn can analyze but not change. With T4 templates, you lose all your IntelliSense, and mixing the metaprogram with the runtime program code is very clumsy ... also, the brick wall between compile-time and run-time code is annoying. (I cannot use a class in the T4 template if I want that same class to exist at runtime, in the same assembly).

    Some of the machanisms that could be used for metaprogramming:

    1. Compile-time template parameters, alongside existing runtime generic parameters. Potentially, compile-time parameters could be not just data types, but literals, code fragments, etc. It would be a major challenge, though, to make this play well in a dynamically-linked environment. The easy way out is to require all compile-time templates to be internal or private.

    2. D recognized that many C++ template "classes" are for things that are only used at compile-time. Perhaps that's part of the reason they introduced "template mixin" which is like a C++ template class, but does not create a new scope -- instead the contents of the template are simply dumped inline at the point that the template is instantiated. Very handy! In fact, this feature by itself provides a lot of the functionality of traits (#5).

    3. Static if and static foreach (usually inside templates)

    4. Allow running of arbitrary code at compile-time, as long as it's safe code. D aims to support exactly this. Since .NET doesn't use traditional linkers, an attribute would be needed to request a function/type to be removed at runtime.

    5. Compiler plug-ins, like in boo -- actually boo has a ton of other metaprogramming features, but I know nothing about them because (last I checked) they didn't write any documentation for them at all. Plug-ins seem like a really easy approach (from the compiler's standpoint) because you don't have to worry about ordering (e.g. no possibility of cycles, where a metaprogram tries to use code that is generated by another metaprogram that relies on the first metaprogram... ugh), and it's very general and therefore very powerful. You would have to standardize a lot of internal APIs for this approach, though (Roslyn as a starting point?), and if you're sufficiently paranoid you'll want to sandbox the plugin (make sure it doesn't use Sockets, etc.)

    6. Code that runs at compile-time could produce strings which are then compiled. Again D has this mechanism, but it is IMO the ugliest kind of metaprogramming, and would be hostile to the refactoring tools we are used to.

    7. Type aliasing (C++-style typedefs)

    8. Extra operators. I assume your compiler has a traditional fixed-function parser, so probably user-defined statements and operators are off the table, but you could offer a couple of niceties for DSLs. For example, I imagine `backquoted` binary and postfix operators*. Then a C#-based DSL would have an mechanism to add new operators. It would be a primitive mechanism, to be sure, having one fixed precedence** and requiring some extra typing effort, but something is better than nothing, e.g. Foo `!->` Bar is better than having to write doesNotImply(Foo, Bar). The postfix operator could be hijacked for unit inference: double accel = 9.81 `m/s^2`;

    * (I did not suggest both prefix and postfix `operators`, for the same reason that a language would never introduce a postfix minus; what would 9 - - 7 mean then? Prefix operators can be approximated with ordinary functions, anyhow.)

    ** (They would have to have some fixed precedence in a fixed-function parser, although powerful rewrite features + a clever metaprogram could rearrange the syntax tree to change this precedence.)

    Whew! This sounds like a lot of work. Ask MS to hire me if you need more manpower ;)

  • i m getting Visual Studio 2005 The remote connection to the device has been lost. Please verify the device connection and restart debugging. plz help me solve this problem...

  • I would like the possibility to compile directly to native code instead of MSIL.

    NGEN is a good AOT tool, but I would rather have the ability to distribute my applications without dependencies to the CLR, with better control about the code optimization. Something like the Bartok compiler in Singularity.

    With the recent focus back on native code, such a compiler option would be great.

  • Mmm. Seems like F# already has most of the features that would be a C# programmers wet dream. It already has immutability by default, higher order functions, record types, discriminated unions, pattern matching, object expressions, units of measure, easy async and parallel capabilites, computation expressions (aka monads), type providers, quotations, currying, partial function application, machinery to enable duck typing, etc... Just use F# today, rather than waiting for some of the featutes to be ported to C# sometime in the future, it ever.

  • As a followup to my previous comment, I am now working on a programming language with multiple metaprogramming features that is backward-compatible with C#, called EC#. Let me know if you'd like details.

Page 1 of 1 (8 items)