00:00:06.720
Hello everyone, thank you for coming today.
00:00:12.000
My name is John Lam, and I work for Microsoft.
00:00:18.359
I want to start off by sharing a little bit of my story and the journey that brought me to where I am today.
00:00:24.359
At the last RubyConf in October, I announced that I was joining Microsoft to work on dynamic languages.
00:00:30.000
That is still true, and I would like to share some pictures to illustrate my transition.
00:00:36.540
This is where I used to live in Toronto, with a big 'sold' sign in front of my house.
00:00:42.480
If anyone has ever moved houses, you know it can get a bit chaotic, especially if there’s not much to take.
00:00:48.300
Here's my dog, looking really confused amongst all the boxes.
00:00:55.620
We had to pack everything, including our kits in boxes. My wife is pretty happy now.
00:01:02.520
Matthew is doing okay too. It was definitely a stressful time.
00:01:08.340
Now we live in Seattle, which is much prettier than where we lived in Oakville.
00:01:14.040
Seattle has a beautiful landscape with trees and mountains, unlike the flat, suburban feel of Oakville.
00:01:19.320
This is where I work now, at Building 43, with Mount Rainier in the backdrop.
00:01:25.560
This picture was taken on one of those rare snowy days in Seattle, which happened to coincide with my arrival.
00:01:31.020
Just to set the stage, the thing I built before coming to Microsoft was the Ruby CLR bridge.
00:01:36.720
Many of the topics I will discuss today relate to the problems this bridge aimed to solve.
00:01:41.880
The challenge is how to enable a dynamic language like Ruby to interoperate with static libraries.
00:01:47.159
This raises an important question: why would anyone want to run Ruby on another virtual machine, be it JVM or CLR?
00:01:53.759
The fundamental reason is to gain access to the libraries that exist on that platform.
00:02:00.119
However, this is quite a complex problem with no straightforward solution.
00:02:05.939
If you're writing Python, for instance, and want to access static libraries, the process will fundamentally differ from how Ruby would handle it.
00:02:13.319
Although there are common elements, the interoperability layer will require tailored solutions.
00:02:19.800
It's important to ensure that writing a Ruby program that communicates with CLR libraries feels natural.
00:02:26.099
We want it to feel like you're writing Ruby, not C# with a Ruby syntax.
00:02:32.640
Throughout this talk, I will share insights that reflect my thoughts on this matter.
00:02:39.840
At various points, I will compare decisions made by the IronPython team.
00:02:47.220
The cultures of the Ruby and Python communities differ significantly.
00:02:52.500
The Ruby community can be quite dogmatic about specifics such as method naming.
00:02:58.620
In contrast, the Python community tends to be more flexible.
00:03:04.440
I'll highlight how these cultural differences have led to various design decisions.
00:03:09.720
Now, I'd like to show this slide, which I love: Kathy Sierra's measure of success.
00:03:15.239
It represents two circles: what you want to do versus what you actually do.
00:03:20.400
The goal is to maximize the overlap between these two circles.
00:03:26.099
Often, they don't align, especially for those early in their Ruby careers.
00:03:32.640
I find that the hours we dedicate don't always lead to progress.
00:03:39.120
Coming to Microsoft was a strange experience for me.
00:03:44.880
I had never worked for a big company before, and I had typically avoided traditional full-time jobs.
00:03:50.520
Transitioning to Microsoft was quite the culture shock.
00:03:57.240
However, despite the overhead, I find that I have a lot of freedom.
00:04:02.040
The transition didn't feel as difficult as I anticipated.
00:04:07.920
Now, I want to talk about some of the more interesting technical aspects.
00:04:14.640
How many of you here are currently writing code on top of .NET?
00:04:20.760
Okay, about five of you. How about on the JVM?
00:04:26.580
Alright, some others.
00:04:32.400
I want to give the audience a quick overview of virtual machine environments.
00:04:40.140
A good way to understand the differences is by writing a simple application.
00:04:46.920
Let's start with a simple C# application.
00:04:53.640
Creating a Hello World app might seem tedious, but it's a good exercise.
00:04:58.920
So let’s write hello.cs.
00:05:05.760
Now we have hello.exe.
00:05:12.540
This program does what you would expect it to.
00:05:18.060
What becomes more interesting is when we consider a utility called Reflector.
00:05:25.200
Reflector is a program developed by Lutz Roeder, a colleague.
00:05:31.560
This program allows you to explore metadata and understand the inner workings of .NET.
00:05:39.960
Lutz Roeder is a fascinating individual who worked on Intentional Programming.
00:05:46.440
Intentional Programming was a significant research project at Microsoft.
00:05:54.960
It sought to revolutionize programming but only really left behind a remarkable editor.
00:06:02.520
Reflector was built by Lutz as a way to establish his identity at Microsoft.
00:06:11.640
He wanted to ensure everyone at Microsoft knew his name through this tool.
00:06:18.240
Now, let's look into how Reflector actually works.
00:06:24.480
When you explore the app we just wrote, you start to see the metadata it reflects over.
00:06:32.400
This tool essentially reverses any arbitrary chunk of Intermediate Language (IL).
00:06:39.720
With the help of Reflector, you can see the representation of your code.
00:06:46.800
It transforms what you've written back into readable code.
00:06:53.520
Reflector is a valuable tool for exploring the .NET platform.
00:07:00.360
Let's now take a look at a simple IronPython app.
00:07:06.120
I want to show you how IronPython translates to IL.
00:07:13.920
Let's see what happens when we compile a simple IronPython app.
00:07:22.200
I often forget the switches for compiling, so bear with me.
00:07:30.000
As it compiles, note how the size of hello.exe changes.
00:07:35.880
Now, let's examine the executed code in Reflector.
00:07:42.060
Navigating this can be tricky because of its size.
00:07:47.520
Inside it, you will notice many interesting components.
00:07:53.400
Let's disassemble the main method here.
00:07:59.880
You’ll see a lot more detail than you would with a plain method.
00:08:06.600
The goal of Reflector is to explore the dynamics of the code.
00:08:13.820
Reflector helps bridge the understanding between Ruby and .NET.
00:08:20.640
Now, let’s discuss the Dynamic methods in CLR.
00:08:26.520
Dynamic methods are lightweight and optimized for quick execution.
00:08:34.500
When you invoke a dynamic method, it first compiles into native assembly.
00:08:41.720
After the first invocation, it calls the previously compiled code.
00:08:47.160
Dynamic methods allow for just-in-time compilation tailored to runtime needs.
00:08:54.420
When they are no longer needed, the garbage collector can reclaim the memory automatically.
00:09:01.560
This feature is essential for dynamic language interoperability.
00:09:07.560
Dynamic methods handle memory management efficiently, preventing memory leaks.
00:09:13.440
Now, let's look at the various techniques for Ruby interoperability.
00:09:20.640
We are working primarily with the Ruby CLR implementation today.
00:09:27.180
Ruby's native implementation (CRuby) allows us to build C extension libraries.
00:09:33.420
Imagine creating a Ruby class that calls a C-based extension.
00:09:39.960
This impacts how we invoke methods between Ruby and CLR.
00:09:45.420
If I want to call a method in C on Foo, we need to bridge that gap.
00:09:52.320
With Ruby CLR, we create a proxy class that looks just like a C# class.
00:09:58.740
This way, method calls are correctly marshaled to the CLR side.
00:10:05.880
Dynamic methods now make this process seamless.
00:10:13.260
To illustrate, we can overload method signatures, even with different return types.
00:10:21.480
But Ruby doesn't allow function overloading based on return types.
00:10:27.780
At runtime, we have to determine which method to call based on the parameters supplied.
00:10:34.560
On the CLR side, we marshal the parameters as necessary.
00:10:40.560
The magic of dynamic methods makes this process easier.
00:10:46.920
In Ruby CLR, we use a combination of method_missing and const_missing to manage method calls.
00:10:54.600
This allows us to build the necessary proxies dynamically when functions are invoked.
00:11:02.760
As we dive deeper, let’s look at specific implementations.
00:11:09.780
For example, we can import the ArrayList type into Ruby seamlessly.
00:11:15.720
Once imported, we can call methods such as add seamlessly.
00:11:23.880
Ruby's syntax naturally integrates with .NET functionalities.
00:11:29.280
You can index into the ArrayList using Ruby’s syntax too.
00:11:35.880
Our events also map naturally into Ruby blocks.
00:11:43.320
When a button click event occurs, it invokes the corresponding Ruby block.
00:11:48.840
This example demonstrates the seamless interaction from CLR to Ruby.
00:11:57.720
The interfaces also present an interesting challenge.
00:12:05.040
We must expose .NET interfaces appropriately within the Ruby environment.
00:12:12.600
The .NET interface becomes a proxy within Ruby’s dynamic system.
00:12:17.520
This mirrors the C# syntax and provides a familiar experience.
00:12:25.740
Now, I want to clarify what this looks like for an ArrayList.
00:12:33.240
An instance of ArrayList will behave just like a Ruby object.
00:12:39.360
I can directly manipulate both from Ruby and CLR without issues.
00:12:45.420
However, challenges arise with the need for method overloading.
00:12:52.680
In scenarios where overloads exist, we must manage type resolution carefully.
00:12:59.520
Issues can occur where Ruby types don't match CLR types.
00:13:06.240
As programmers, we must address these discrepancies through shims.
00:13:12.240
The process helps distinguish between methods and ensures correct invocation.
00:13:19.200
The overall goal is for Ruby developers to feel at home while working with .NET.
00:13:26.040
The techniques implemented in Ruby CLR promote natural syntax and usability.
00:13:32.760
In scenarios involving generics, we need to ensure clarity for developers.
00:13:39.600
Generics can sometimes complicate method resolution.
00:13:46.680
However, we implement necessary limitations to keep operations straightforward.
00:13:52.920
When methods don’t have overloads, the calling becomes much more efficient.
00:14:00.240
This is a crucial aspect of how Ruby interacts with .NET libraries.
00:14:07.320
A notable design consideration is how we manage method overloading effectively.
00:14:14.040
We want to create methods that are intuitive for Ruby users.
00:14:21.840
There’s an interesting trade-off when developing features.
00:14:28.920
If overloads are ambiguous, developers might get lost in method resolution.
00:14:36.240
This confusion can hinder the user experience.
00:14:42.600
By providing clear interfaces, we reduce complexity.
00:14:49.800
Ultimately, the aim is to create seamless integration while using Ruby on .NET.
00:14:56.880
We uphold the principles of Ruby's dynamic nature throughout the interoperability.
00:15:04.920
In closing, I hope to encourage further exploration of Ruby CLR.
00:15:11.560
There's much more to discover, and I look forward to the advancements ahead.
00:15:18.480
Thank you for your attention. I'm happy to take any questions.
00:15:27.120
What if someone only has a PowerPC system?
00:15:35.760
You can still use Mono, but challenges exist.
00:15:41.400
The lack of a C++ compiler on Mono creates barriers.
00:15:48.600
Nonetheless, there are community efforts addressing this.
00:15:55.440
The contributions of IronPython provide some valuable insights.
00:16:01.800
There are ways to navigate the Mono challenges for Ruby CLR.
00:16:08.640
You might need to disassemble and recompile for compatibility.
00:16:14.520
Questions, feedback, or future suggestions are always welcome.
00:16:21.360
Thank you for engaging, and I appreciate your attention.