It’s been a long ride – starting in 2007 when IronRuby was introduced running in Silverlight. Things started out slowly, but for the last year we’ve moved pretty quick, have gotten great feedback, and IronRuby is due for another bump:
We’ve exceeded our goals for 1.0, and still plan on further excess before 1.0 is final. Let’s dive into our top goals: performance, compatibility, and CLR integration.
We’ve been tracking performance against MRI 1.8.6, which though isn’t a final performance goal, it’s a good measure of performance for a 1.0. In the next major release we’ll start tracking MRI 1.9. In general we’re a significantly faster than MRI, but still a tad unacceptable compared to JRuby – that needs to be fixed before 1.0.
We measure compatibility against RubySpec, as well as some popular Ruby libraries (only the top-used ones are shown here). We’re over 90% for every group of tests. In practice, compatibility is being tested against almost every library we can get our hands on, which is a ton, so I feel confident IronRuby 1.0 will be a very compatible Ruby implementation.
As I said in a previous post, this compatibility measure is against 1.8.6; IronRuby does not yet suppor 1.9 completely, though we may quickly change our opinion on this.
CLR integration is very flushed out, supporting using all CLR classes, calling all methods, properties, etc, generics, inheritance, and all the other CLR features exposed to managed languages such as C# and F#. The only missing hole is generating actual CLR types and backings for Ruby types, though we feel this is an OK feature to ship without, because the work-arounds are simple. However, it will be a priority to fix in the next major release.
With RC1 being released, RC2, 3, etc. will come as the community reports issues that we all agree must be fixed by 1.0 final. As far as the core team’s priorities, we want to fix startup and throughput performance issues, as well as get through the backlog of bugs.
After 1.0 is released, we’ll probably take a bit of a break, but then look to do some features we didn’t get to finish in 1.0, as well as Visual Studio Integration, since it’s the highest voted feature for VS2010:
Imagine you’re building a program to help create animations, visualizations, and other interactive applications. The requirements are simple:
2D rendering surface with simple primitive shapes
Simple animation support – callbacks for each frame and each object on the canvas
User-loadable “macros” for drawing and animating
A .NET developer can easily code up the first two requirements in C#, but implementing the third will be tricky. What does a macro look like? How do I discover them? How can I make it interactive? Why is this so hard!? This scenario requires the user to input some data, and the program must make an animation out of it; the data of your program is the code. Here are the options most .NET developers would come up with:
Domain specific language – people usually cop out here and make it XML-based, which happens to produce the most human-unreadable code ever. This DSL could also be GUI-based, but you won’t get any programmers interesting in extending your app that way.
Completely punt on the interactivity and require the macros be .NET DLLs.
Find a way to use C# interactively - either using CodeDom to compile and run C# code dynamically (much like ASP.NET does), or code-generate a valid C# class from the snippet, compile it to a DLL (aka shell out to csc.exe), loading that DLL, and finally reflecting over that DLL to call the user’s code. This is, of course, ignoring the question of whether C# is a good macro language or not. It’s worth noting that Mono supports hosting it’s C# compiler, so you could do more dynamic things with C# through Mono.
Given all that talk about Ruby before, let’s try using IronRuby to write these macros. Here’s a C# app to start from:
The starter app does ABSOLUTELY NOTHING; just a Window with a Canvas and a bunch of textboxes for coding. Keep in mind this is just a demonstration, and this app could have been written entirely in Ruby, but the point is to show .NET developers how powerful an embedded scripting language can be.
Setting up your environment
.NET developers have choices for development environments: mainly Visual Studio or SharpDevelop, or even the command-line and text-editor (I left out MonoDevelop since Mono doesn’t support the Windows UI stuff I’m doing, but a future version will be able to run in Mono). I’ll be using Visual Studio 2010 Beta 2 for this walkthrough’s screenshots and examples, specifically because it C# 4 has special dynamic language features, but you can also use C# 3 with Visual Studio 2008 (free version here), or just stick to a text-editor and MSBuild.
If you’re using .NET 4.0, sketchscript\sketchscript.sln is the solution file you want to use. The .NET 3.5 version is sketchscript\sketchscript3.5.sln, but seriously, try out .NET 4.0.
I haven’t tested it out in VS2008 yet, so please bare with me. If you’re feeling adventurous, you can fork my git repo, get it working in VS2008, and I’ll pull your changes in.
Adding references to IronRuby
If you downloaded SketchScript from the above link, you’ll find four DLLs required for embedding IronRuby in the sketchscript\ironruby directory. Add those as references to the sketchscript.csproj:
In case you’re curious about what each DLL is: IronRuby.dll is the IronRuby compiler, while IronRuby.Libraries.dll is the core libraries of Ruby. Microsoft.Dynamic.dll are the APIs that IronRuby depend on for DLR compiler features, and Microsoft.Scripting.dll is the DLR Hosting API.
If anyone who has used IronRuby before is thinking there are missing DLLs, then you’re right. IronRuby’s Microsoft.Scripting.Core.dll has been integrated into .NET 4.0 as the new System.Core.dll. This also removes the need for Microsoft.Scripting.ExtensionAttribute.dll.
Embedding IronRuby
Now let’s get that code window working; first add some using statements at the top of MainWindow.xaml.cs:
And some fields to hold onto the scripting engine anywhere in the MainWindow class:
Now initialize the scripting engine; add this code to the Loaded event action, after setting the OutputBuffer but before the KeyBindings() call (around line 71):
And lastly let’s run the code when Ctrl-Enter is pressed. Since that’s already set up for us, all we need to do is add this code in the RunCode method, right at the "TODO" comment around line 92:
And that’s it! Now you’ll be able to run some actual Ruby code:
Interacting with the host application
Though Ruby code can run, there is no obvious interaction with the host application. That black void of a canvas on the left would be completely useless if it wasn’t accessible from Ruby code, so add this single line to the Loaded event action, before the KeyBinding() call:
Note: if the host application didn’t do this, it would still be possible to get to the canvas from Ruby code, but the script writer would have to do it themselves:
So, as a general rule-of-thumb, have your host program decide what parts to extend to script code, and have the script code only use that object-model, though their may be ways around it.
Trying it out
Now that there’s a way to draw on the canvas, play around with drawing random things on the screen. Here’s a little script I’ve been playing with:
Which draws this:
Ooo, pretty! So without much effort we have a very extendable application. Before you get carried away playing around with making pretty things, there’s one more thing to do to make this app really awesome …
Animation support
While animations could still be built with IronRuby’s native thread support or WPF animations directly from Ruby code, it’d be nice for the host to provide some simple animation support, like a callback that fires for every frame, and even a way to attach animations to any object.
The host currently supports these two callbacks, but they need to be wired up. Add the following code at the bottom of the Loaded event action, before the call to KeyBindings():
And also add this call at the end of the RunCode method:
Lastly we need to implement CatureAnimationCallbacks, by looking for special method names to get a hold of. Look for each_frame as the EachFrame action, and each_object as the EachObject func.
Now 30-times-a-second the host will try to call each_frame, and it will call each_object once for each element on the canvas, store the return value on the actual element, and then try to call an update method on that stored object 30-times-a-second. This lets you either run random animations, or specific behavior for objects.
A good animation example is bouncing, so let's run the script that produced all the squares first, and then run the following code to make them all bounce.
And now it should look something like this:
There are more goodies to run in the features directory, but try writing your own fun little animations. Jim Deville ported the tutorial from Jeff Casimir’sCode of Art talk, which is pretty fun to play with, so if you make your own please post a comment with a screenshot and code!
And there you have it, IronRuby embedded to do interesting things. In case you missed any steps along the way, here's the full diff against the initial download.
Let’s be honest: not everyone uses Ruby. I know, it hurts to hear, but it’s the truth. To get a general idea of how bad it really is, let’s look at indeed.com’s job trends for Ruby, Python, Java, and .NET, and assume that’s a good measure of usage:
Holy crap! Regardless of the actual numbers, we all know what this graph is saying to be true. But why are dynamic language’s so under-used? Aside from the obvious, like fear of something different, the dynamic language community hasn’t sufficiently answered the “why” questions to the other camp, like “Why should I use Ruby if I already know .NET?”, and “why even bother.” Our answer has always been “Productivity, expressiveness, blah, blah, blah”; that turns out to be a horrible way to sell dynamic languages to people who love C# or Java for it’s productivity and expressiveness. =) However, their fears are justified; Ruby’s main usage today is for stand-alone apps (mainly websites, but there are some client apps), so they assume Ruby can’t be use it in their existing environment.
Let’s solve this!
Let’s make it easy for those programmers at the top of the graph to use the languages at the bottom of the graph. Ruby gets to expand its ecosystem, and enterprise developers get a great dynamic language to use. Ruby is nicely position for this specific scenario since implementations of Ruby exist for both Java and .NET, so Ruby’s usage could become more on-par with Java and .NET. And here’s the way we make this happen: .NET and Java developers can easily embed Ruby into their existing applications for scripting.
Also, since I work on IronRuby, I’ll be talking about this in relation to IronRuby and .NET from now on, though the same arguments work for JRuby and Java (and Jython). Check out the embedding JRuby page, and also how all this work in Jython.
The .NET people reading this might be smiling, but the Ruby people want to vomit … (maybe partly because of .NET, but in all seriousness) … because of the word “scripting”. I know, I too hate the negative associations “scripting” has; when I first started working at Microsoft I was openly against naming a component “Microsoft.Scripting”, but who listens to the new guy? For those who don’t get it, “scripting” makes these amazing languages sound like they are only useful for little toy things, and not for real work. Anyway, this plan takes advantage of that misconception, so don’t look at it as such a bad thing. :)
Why and How?
Ok, .NET developers, stop reading … you’ll ruin the surprise! Just kidding. I love you. Read on …
Since .NET developers see Ruby as a scripting language, it’s not a stretch to convince them that Ruby is good for embedding into their applications as a extensibility feature; allowing customize their application with bits of Ruby code. Here’s where all the Trojans jump out of the wooden horse. Getting Ruby into existing .NET applications is a much easier way for those developers to learn and use Ruby, rather than asking them to build a new app from scratch, or just look at tutorials, docs, etc, without having a good reason to. If .NET developers want to look at Ruby for use in their existing projects, then we’ve succeeded; it’ll then be pretty obvious that they can do real things with these so-called scripting languages. They’ll probably start using Ruby to prototype new features in their existing system, and then either keep that code as Ruby, or port some of it to their main language. Keep in mind, the goal isn’t to steal people from .NET – they would have left long ago like many of the Ruby community did – it’s to make Ruby co-exist with these more “enterprise” systems, and overall make software development fun again for everyone.
But how do .NET developers really benefit from having a scripting language they can use from their current environments? Three words: No More XML. XML seemed to be the solution to all .NET developer’s problems since it was a way to make their environments more dynamic. It is easy to parse and walk XML, making it also easy to attach some meaning to seemingly meaningless angle-brackets. One could implement anything using this technique, even logic. Which is why XML became a dynamic language and meta-programming tool for .NET. But really XML is a work-around to these static languages lacking the ability to be treated as both code and data.
Being able to use your code just like your data is liberating. For example, running Ruby code from just at string:
IronRuby supports the DLR Hosting API, a language-neutral script hosting API for .NET. For instance, supporting another is just as easy as changing the 2nd line to "IronPython".
Imagine doing this with XML; you’d have to somehow encode what element and field you want to modify, along the value to update it to, and then use something like reflection to interpret the XML and do the work. And that’s just for this simple example of setting the text of a TextBlock. So using a real programming language allows for endless extensibility-possibilities. Ruby is especially interesting since it can be simple enough for non-programmers, but powerful enough for adding full features.
Software which allows simple extensibility, like Firefox and Rails, tend to always create an ecosystem of extensions around them, which end up being one of the most compelling features of the program. Maybe that next app could be yours?
First a little background for those new to IronRuby …
IronRuby is a Ruby 1.8.6-compatible implementation, with support for some 1.9 features like string encodings. IronRuby is built on-top of the Common Language Runtime, so certain runtime-specific Ruby features are not supported on IronRuby, like callcc, ObjectSpace, and native extensions. However, local-continuations are coming, and we are considering FFI post-1.0 to support native code.
IronRuby runs on the CLR (2.0 SP1+) and Mono (2.0+), so IronRuby runs on a ton of platforms, including Mac OS and Linux. IronRuby also runs in the browser with Silverlight and Moonlight, a 4MB runtime which allows you to use Ruby to build “rich internet applications” … basically anything doing vector-graphics, webcam, audio, etc in the browser.
To at least prove IronRuby runs on the Mac, here’s IronRuby installing the activerecord gem:
Yay =P I spoke in-depth about this at OSCON this year, so if you’re interested in how IronRuby runs cross-platform, please read my OSCON 2009 post.
While “IronRuby running everywhere” is a great bullet-point, when would you use it instead of another implementation? I’ll briefly mention a few Windows-focused reasons, but the focus will be on things that work regardless of your platform.
One of IronRuby’s goals is to be the premiere Ruby implementation for Windows. Any type of development possible on Windows should be great on IronRuby; GUI, console, DirectX, etc. And some of these benefits also go cross-platform; for example using .NET’s WinForms for GUI apps will let you run the same app on Window and Linux.
Even systems management tasks can benefit from IronRuby – a scripting language that Windows developers can use for anything – like all the languages that come standard on Mac OS and Linux distributions.
Web developers can also use IronRuby to deploy their Ruby-based apps on: IIS is a great web-server, and IronRuby will make it easy for Windows shops to justify using Ruby on Rails or any other Ruby-based web framework. An interesting factoid: 51% of traffic on wiki.rubyonrails.org is from Windows users (data source: Matt Aimonetti and the Rails Core Team) – I’m not quite sure what that means, but at a minimum it means people who have an interest in Rails are using Windows.
Ruby in the browser
One of the great features of IronRuby is it’s ability to run in the browser. Unfortunately there isn’t a ton of information about how to do this, but a nice set of documentation is being prepared for when the new IronRuby site goes live. Here’s a sneak peak into how easy it is to run Ruby in the browser:
Great, it’s easy, but what can I do with it? Right now, the best source of documentation for this is my Back to Just-Text with Silverlight paper. A place-holder page for where all this info will be is http://ironruby.com/browser, but like I said, there is much more to come. The Gestalt project has a ton of cool samples and information as well, but most of this will eventually live on the actual IronRuby website.
Other than this being some cool technology, how could it actually be useful? I would not recommend porting all your JavaScript to this, but this is useful anywhere you need to show graphs, charts, anything visually oriented, or really anything where the browser feature-set isn’t enough. Rather than writing in ActionScript for Flash, you could use Ruby and Silverlight. Once you have a good reason to require Silverlight for a page, then it opens up the possibilities for using Ruby in the browser for things you used to use JavaScript for. For example, imagine writing both your server and client code in Ruby, and even reusing code between the two.
It may not be the only way to run Ruby in the browser, but it’s the most web-friendly. It’s worth noting that JRuby lets you write Ruby inside a Java applet, but that requires Java to be installed. While Java still has more market-penetration than Silverlight, Silverlight’s tiny size makes this an irrelevant point for me. Also, Silverlight is installed on 45% of the connected internet machines, so Silverlight’s market share is briskly increasing.
Also, HotRuby lets you write Ruby which compiles down to JavaScript or Flash, and while the demos are very impressive, the implementation is very not completed, and hasn’t been updated for almost two years. HotRuby requires the Ruby source code to be compiled on the server with YARV, and then the serialized bytecode is run on the client with a JavaScript VM for Ruby (which is the incomplete part). It’s a promising project if someone picks it back up.
Considering those alternatives, IronRuby’s script-tag development and just-html deployment make it the best experience for writing Ruby browser apps currently.
Anyway, I’ll write more about this when I can point you at a real website that shows what all this can really do.
Now that the turkey has settled and I’m back in Seattle, I’m finally getting around to writing about my time at RubyConf 2009 in Burlingame, CA (not San Francisco, liars! ;)). I spoke about IronRuby, got to meet a bunch of the other implementers, and overall had a great time. Jim Deville also got to come along for free, since Microsoft was a Silver sponsoring of RubyConf – next year we should sponsor the internet-connections since everyone using Chad’s room’s wireless was, well, fun … but no promises ;)
My talk was all about how IronRuby is extending the reach of Ruby. The two areas I focused on was “running in the browser” and “scripting existing applications.” And all that was sandwiched with a overview of the project and a status update. All content from the talk can be found in my RubyConf 2009 GitHub repo, but I’ll walk you through the talk with a couple of posts:
Here’s my strategy for attending talks: open laptop and code until the speaker catches my attention. When bored, go back to coding, and repeat. I got nothing done at RubyConf; irritating and refreshing at the same time. Maybe it was the shotty wireless, but I’ll stick with saying the talks were awesome. Here’s what I liked:
Keynote - Yukihiro Matsumoto
Matz outlined a new language called ZEPT: A general-purpose dynamic language which is great for distributed programming and metaprogramming. After explaining this very familiar language in some detail, he then turned it around and essentially said, “Wait, it’s Ruby! Kinda.”
While Ruby’s syntax is great for metaprogramming and DSLs, it needs work for distributed programming to be really great, but this is being worked on. Ruby currently has most of the building blocks for distributed programming, like lambdas, enumerators, and continuations, and things like a lazy-array are planned for future versions of Ruby. He closed with, “You can create the future of programming by working on Ruby,” and that there are more advances in internal DSLs in Ruby’s future.
Jeff handed out actual paper for his talk, so he gets props for that. He demoedruby-processing, a port of the Java Processing library for making fancy graphics and visualizations; it uses JRuby. The main demo was a very simple “click-and-make-a-random-sized-circle” … so simple I had to rip it off for my talk. So, I sent Jim off with my demo to hack it up, and now we’re close to having a full 2D-only-port of ruby-processing for IronRuby. More about that later though.
FFI, Foreign Function Interface, is a DSL for describing C-libraries in Ruby; very similar to writing a header file. A benefit of using writing an C-extension based on FFI is that it should be compatible with many ruby engines, as the compatibility burden is placed on the ruby engine rather than the extension implementer. Supporting FFI will be a reality for IronRuby after 1.0; I’ll put this on the project’s TODO list. Anyone interested in starting an FFI implementation for IronRuby?
Jon’s talk got me smiling, since it’s the same problem I tried to solve with IronRuby on the client and server, but decided a Rails-specific solution was just good for a demo. He started his talk out with “browser plugins are not an option” … crap =P. Jon walked through his design process, until landing on a solution that basically cuts Ruby out completely and uses JavaScript to build both the client and the server portions of a webapp, sharing implementations and data. Wow, that’s one way to do it. :)
I actually didn’t get to see this since it was at the same time as my talk. I saw someone say on Twitter that this was one of the best attended talk at RubyConf. Jerk :)
Charlie talked about Duby and Surinx, his Ruby-derivatives. Duby is a statically typed Ruby-like language, while Surinx is a dynamic-typed language which depends on invokedynamic. Duby’s nice in that it’s not very JVM-specific (other than the backend), so an upcoming project of mine will be to write a CLR backend for this – having a Ruby-like language that is basically a facade on the CLR will fill in a lot of the holes we have with IronRuby, and hopefully influence some future IronRuby work – just like JRuby is planning.
Other Thoughts
No implementers care about Ruby 1.8.6 anymore; Ruby 1.9 is the focus for all future work. MacRuby isn’t even supporting 1.8.6. So why should IronRuby support it? Granted, JRuby supports 1.8.6, as well as other 1.9 features, but they have been a “real” implementation for a while. When IronRuby actually starts to get production apps, do we really think Rails 3.0 (which is Ruby 1.9 focused) won’t be standard by then? Personally I think IronRuby should re-evaluate it’s reasons for supporting Ruby 1.8.6; if we support 1.9, compatibility will get better as time goes on … where as supporting 1.8.6 is a sure-fire way to ensure a decrease level of compatibility in the future if we don’t keep up. Thoughts?
Also I got to meet Matt Aimonetti, of the “Pr0n Star” fiasco, but I’ll let that slide :) He’s seems genuinely excited about using Ruby in the browser with Silverlight, and also has always offered his help with promoting IronRuby on Rails; he interviewed me on the Rails blog not too long ago. I look forward to seeing greater collaboration between the rest of the Ruby community on IronRuby, and hopefully this is the start.
CodePlex will continue to be the tool we use for project management and releases, but all end-user information will be on IronPython.net. Also, the .com domain still points at the super-old site, but will redirect to this site shortly.
The most notably addition is the .NET Integration Documentation, a thorough set of examples and descriptions of using IronPython with .NET. Considering this is IronPython’s main purpose, it’s amazing we got away with having hardly no documentation for this long … I guess the .NET integration is just that intuitive :) Anyway, please give it a read and let us know if you have any suggestions.
There’s a ton left to do!
This site is very much a shell of what it could be, and I’d love for the IronPython community to help out here. Here are a few things I’d like to add to the site in the very near future; please let me know if you’d lie to help out, or have other ideas:
Who’s using IronPython? A list of companies, public websites, and any type of application which use IronPython, in any way, would be a great addition to the site. If you’re taking a large dependency on IronPython, I’d also love to have a more in-depth write up posted about you: Resolver Systems should definitely be on this list :)
Many more code-snippets for the front-page which show IronPython’s strengths. Maybe a random code snippet every time you refresh, or a auto-cycling with some simple navigation to pause and go back-and-forth between them.
Better organization of community articles: the IronPython community produces an enormous amount of documentation through blogs, articles, screencasts, and other mediums on the web. The IronPython website could never replicate this, so let’s make it a place to organize this information, grouping documentation together by topic and linking to the original author’s site.