Author: Chaur Wu
Publisher: Apress 2010
Aimed at: .NET programmers who want dynamic language features
Pros: Very detailed
Cons: Too focused on the internals
Reviewed by: Nikos Vaggalis
As well as reviewing the book, Nikos Vaggalis provides a quick overview of DLR. So if you want an enlightening tour read on ....
According to the Apress road map 'Pro DLR in .NET 4.0' is an advanced book - you have to master 'Introducing Visual C# 2010' first and then 'Pro C# 2010 and the .NET 4 Platform', before you tackle it. It also sets as a prerequisite knowing a dynamic language, like Python, although I find that this does not pose so much of a problem
So what is the DLR?
Put simply it is a runtime that sits atop the CLR and hosts dynamic languages. This is explained in the Introduction and Chapter 1 is concerned with going through the areas where the DLR can be used:
It makes implementing a new language, be it a dynamic, application or domain specific one, much easier to build since you can use ready made parts and leverage existing functionality; for example instead of implementing a GC you plug into the CLR's GC!
Then you can mix and match objects from different languages. For example calling a IronPython library from C# and vice versa (or even call the .NET graphical library from within IronRuby) I think that is the groundbreaking issue here, not only connecting dynamic languages with dynamic languages but also dynamic with static ones.
Chapter 1 gives an overview of the parts comprising the DLR and their interrelations, explains the difference between 'runtime', run time and compile time using a good pictorial notation, and briefly touches the subject of Expressions which are the backbone of the DLR.
The typing system subject is also brought up; strong typing, static vs. dynamic. These are difficult concepts and the compressed explanation in this chapter attempts to give a quick overview of concepts that crop up throughout the book, since discussion of dynamic languages makes them unavoidable. This is a topic I have covered for IProgrammer with my series of articles, Type Systems Demystified, so you might want to read these to get a good understanding.
Chapter 2 examines DLR expressions in depth. These are the common-denominator that brings all languages into the DLR platform. To sum it up in a few lines: each language has its own parser which parses the source code and results into a AST (not optree;abstract-syntax-tree is more flexible). For example IronPython produces an AST and IronRuby produces its own AST as well. Both ASTs are then transformed into a DLR AST, which essentially IS the Expressions, so that everybody speaks the same language. The tree itself is composed by nodes that are objects which represented code. The idea is that representing code as a graph instead of bytecode/IL, allows walking it, manipulating and extending it (using the Visitor pattern), semantic transformation of the tree (as the example with the custom Linq query provider in chapter 8 demonstrates) and applying optimizations.
Then the expression tree can be directly interpreted by the DLR runtime or be compiled into bytecode/IL for execution by the CLR.
Chapters 3 and 4 explore the concepts of late binding and how it can be implemented in your own language using a component called 'binders'. Binders also enable caching late binding calls which aids in increasing a dynamic language's performance. Performance was traditionally an area in which a dynamic language was disadvantaged vis-a-vis statically typed languages.
Language interop is also explored in Chapter 4, which shows how to use dynamic Ruby objects from within Python code. It also provides a good overview of the differences between static and dynamic objects and examines how a static language like C# can interop with a dynamic one and vice-versa. Later on it focuses on how to implement custom binders for your own late binding logic
Chapter 5 again builds on the foundations of dynamic objects laid down in the previous chapter and goes one step further by not only using a ready made dynamic object but also showing how to implement a dynamic object yourself.
Chapter 6 uses binders and dynamic objects to enable embedding or hosting a language within another language. The binders play their role in exchanging objects between the host and guest and allow to program against the DLR hosting API without having to know each languages' proprietary hosting interface. It also explains why the DLR simplifies language interop and how cumbersome the process was before the DLR by just relying on the CLR
Chapter 7 looks at how the DLR can be enabled for Aspect Oriented Programming, a new paradigm for separating crosscutting concerns and isolating them in smaller self-contained parts, the so-called aspects
Chapter 8 tackles metaprogramming which is used for altering a class/instance definition at runtime (add or remove methods) a feature inherent in a dynamic language but not in a static one. So now, C# can take advantage of the DLR to get metaprogramming characteristics.
This chapter also reinforces the what we know about Expression trees; there is an example of implementing our own Linq provider by interpreting the expression tree ourselves rather than the tree being interpreted by DLR.In essence we give the expression tree our own semantic meaning and the provider takes the expression tree and executes it against our own data source. The advantage of this is that the queries are decoupled from the data store so instead of Linq to Sql we can make Linq to our custom-object and execute queries against it.
Chapter 9 creates a domain specific language (DSL) that overrides some DLR shortcomings. Mainly hosting non-DLR based languages with DLR based languages like using IronRuby and Powershell together. The chapter is a good example of creating a grammar for our language using ANTLR and an overview of a custom runtime component.
Chapter 10 allows scripting to extend our program by exposing an object model for interfacing with the outside world. This is analogous to an application (Excel or Word,say) which supports automation and exposes a COM component so users can take advantage of that feature and write scripts against it.
Chapter 12 completes the book with a comparison of the CLR+DLR to the Java VM.
Summing up I will say that for the most part, this book treats the DLR as a white box. It takes a deep look into the internals of the DLR and how you could you use its facilities to your advantage. Although it targets the use of the DLR for day to day programming I find that for the most part concerns language implementers or for specialized usage such as implementing an AOP framework, or building your own Linq provider.
However there is information and takeaways that you can get immediate benefit from, like for example the chapter on Silverlight, manipulating XML documents using the DynamicObject from the .NET dynamic library, the material DLR hosting and language interoperation, metaprogramming/altering a class definition at runtime, and application scripting language which gives users scripting capabilities.
Also the book has a good overall educational value since throughout it you are getting in touch with various concepts such as how a VM machine works, parsing and ASTs, tree transformations, typing static,strong,dynamic,closures, late binding,AOP,DSL,Linq etc.
Personally I would welcome more examples of using the DLR as a black box, not to be concerned with the internal workings but for more straight forward business use. For example, instead of exploring what happens behind the scenes when adding two dynamic types of different runtime types, which concerns language implementers, I would also like to see more practical examples; say adding a dynamic integer to a dynamic string, experience the runtime type checking of the dynamic type and display weak typing properties.
Other topics I would have liked to see included:
interop with COM components, for example manipulating an Excel application without having to use P/Invoke
the dynamic type and its relation to Reflection
how the dynamic object compares to System.Object
multiple method dispatch
It seems like the combination of the CLR and the DLR have solved two of the main obstacles of porting dynamic languages to the .NET platform; closures and polymorphic objects (dynamic type). Will it also support continuations? it remains to be seen but even the core support/hosting/interoperation with dynamic languages is debatable since MS dropped the implementations of Ironruby and Ironpython; it even looks more doubtful if you consider that a Ruby or Python porter would prefer to port the language to Parrot VM rather to the MS DLR.
Hence it looks like everything boils down to using the DLR for giving dynamic language capabilities to the .NET static languages.
Nevertheless, this is the definitive guide to the DLR as well as an intriguing book - so I recommend it to you.