Much hoopla has been generated across the community about dynamic languages; much of it is spoken in the same glowing terms normally reserved for unicorns and rainbows. Some of it is deserved, some of it isn’t. All of it seems to surround two languages-JavaScript and Ruby-but in fact, several other languages, three of which I’ll present here, offer some distinctly interesting and useful features.
Twenty years ago, I took a contract building a standalone desktop application for a small firm. I was the die-hard hard-core C++ developer who prided himself on knowing the four different kinds of smart pointers, not to mention all of the Gang-of-Four design patterns and the C++ template syntax. But as I scoped out the project, it became apparent to me that this program didn’t cater much to C++. It was a lot of file manipulation, writing a file here, reading a file there, copying a file to this other place and so on. And they wanted a small database to store some configuration, and… The more I looked at it, the more it sounded like this was a problem for… (dare I admit it?) Visual Basic.
Long-time VB developers know what’s coming next.
I presented my position to the boss, an IT guy who clearly wanted to make the transition to development, and his response was emphatic. “This is an application that the firm is going to depend on, so it has to be written in C++.” When I asked him why, he said, point-blank, the way one lectures a small child, “Visual Basic code is interpreted, so it’s slow. It doesn’t have a type system, so code written in it is buggy. And it runs on top of a garbage-collected virtual machine, which means it’s bloated.” And so on.
I often wonder what that guy thinks of the success of the JVM, the CLR, Parrot, and LLVM, not to mention Ruby, Python, JavaScript and Perl.
Well, maybe not Perl. Perl just sucks.
Rise of the Dynamics
One of the core facets, typically, that makes a language a “scripting” language (as opposed to a “system” language like C/C++ or Pascal) is that the scripting language is interpreted rather than compiled. In a world dominated by just-in-time compiled bytecode execution engines like the JVM and the CLR, these definitions get a little fuzzy. Let’s not argue that point-it’s not incredibly important anyway.
What is interesting about dynamic languages is that the presence of that interpreter gives us an interesting ability, one that goes underutilized within most enterprise projects: we can embed the interpreter into another project and use the scripting language from within our own applications. Imagine business rules written by business analysts and stored in a database for your web application to retrieve and execute, for example. Or imagine being able to modify the code on the fly from within the application, usually in response to user requests or fast-moving business logic changes. Or imagine using the “scripting” language as a way of storing configuration data that has some logic within it (to differentiate between users, roles, servers, you name it). In fact, this latter example is hardly new: James Gosling, the inventor of Java, once said, “Every configuration file becomes a scripting language eventually.” (I’m looking at you, app.config.)
In some cases, the language in question can be compiled directly to bytecode and executed alongside the code we write in C# or VB (or F#, if you were paying attention to Aaron Erickson’s article from Mar/Apr 2012 issue of CODE Magazine, Quick ID: 1203081). This means we can take something of a Marxist approach to languages in a project: “From each language, according to its abilities. To each project, according to its needs.”
In this article, I want to show you a few dynamic languages you’ve probably not seen before, and how to use them from within traditional C#/VB applications. I’m not going to suggest that you use all of them at once, nor even that this is a “must-do” kind of thing. But, hey, if the shoe fits….
Note that I’m not going to spend a lot of time talking about IronPython and IronRuby because they’ve already gotten some good press in the past. It’s likely that readers of this magazine have run into them before.
Note, also, that I’m not trying to jump into the “dynamic vs. static” debate and weigh in on the side of dynamic languages as being “better” than static languages (whatever that means). To be honest, I actually prefer languages that have a strong type system behind them, like F#, but much of that is because I tend to write code behind the scenes, rather than the front-end code which generally lends itself better to the dynamic end of the language spectrum. (I cite as exhibit A the incredible success of Ruby on Rails.) To be perfectly frank, I believe in a polyglot world, one in which we use a variety of languages to solve the world’s IT problems.
And these are three of the languages I think you should think about using to solve those problems, above and beyond the ones you already know.
Lua
Lua is probably the most widely used scripting language you’ve never heard of. The language itself is a freely-available open-source object-oriented(ish) language hosted at http://www.lua.org. The reason for its popularity is simple: Lua was designed from the beginning to be easily hosted from C/C++ code. This made it very attractive to game developers and designers, allowing them to write the high-performance code in C or C++ and the game rules and triggers and game logic in Lua, even opening up the Lua scripts to third parties (like gamers) to customize and extend. World of Warcraft does this, and it has spawned a cottage industry of gamers-turned-programmers who customize their WoW experience with plugins and add-ons and extensions, making the WoW ecosystem just that much more fun and interesting.
The original hosting interface for Lua is, as mentioned earlier, based on C/C++ code, but fortunately the Lua community is every bit as active as the Ruby or .NET communities. A .NET-based adapter layer, LuaInterface, hides the .NET-to-C++ interop parts, making it ridiculously trivial to host Lua code in a .NET application.
Getting Started with Lua
LuaInterface is, like Lua itself, an open-source project, and lives at http://code.google.com/p/luainterface/. Currently, the best way to use LuaInterface is to pull down the source, which is a trivial exercise in Subversion. Once it’s on your machine, it’s an equally trivial exercise to build it in Visual Studio.
One note: there are a few mentions on the LuaInterface wiki about build errors around “mixed-mode” assemblies, but I didn’t run into this. I did, however, find that the test executables (LuaRunner) were missing an app.config in the project, which breaks the build. It caused no harm to remove the app.config reference from the project and build, so I suggest doing so. Fact is, we don’t really want the test executables anyway-we want the library for our own uses.
Before we go much further, test the LuaInterface build: in the “Built” directory next to the LuaInterface directory, you should find a compiled “LuaRunner.exe” (assuming you got it to build). From the Built directory, run:
C:> LuaRunner ..\lua-5.1.4\test\hello.lua
And you should get the traditional greeting.
Writing Lua
Lua is an object-oriented(ish) language, in that on the surface of it, it appears to have a lot of the same basic concepts that the traditional imperative language developer will find comfortable: primitives, objects, and so on. In Lua, everything is dynamically resolved, so types don’t play a major factor in writing code. Functions can be either part of objects or stand-alone. The usual imperative flow-control primitives (if/else, for and so on) are here. Variables are untyped, though Lua does have a basic concept of type within it-specifically, variables are of only a few types, strings, numbers and so on.
Readers familiar with everybody’s favorite Web scripting language will probably have already figured this out: In many ways, Lua conceptually fits into the same category as JavaScript. Lua’s syntax is arguably much simpler, though, with far fewer “gotchas” within the language.
For example, consider the following:
Account = { balance = 0 }
function Account:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Account:withdraw (amt)
self.balance = self.balance - amt
end
function Account:deposit (amt)
self.balance = self.balance + amt
end
function Account:getBalance()
return self.balance
end
This is a class in Lua. To be more precise, Lua has tables, which aren’t relational tables, but essentially dictionaries of name/value pairs. In fact, technically, this is a collection of functions stored in a table that will make up an object. So, for example, when I write the following after it:
a = Account:new { balance = 0 }
a:deposit(100.00)
print(a:getBalance())
The console will print 100.
Without going a lot deeper into Lua syntax (which is a pretty fascinating subject in its own right, by the way), one thing that’s important to point out is that Lua lacks classes entirely, just as JavaScript does; both are prototype-based object languages, in that “inheritance” is a matter of following the prototype chain to find methods that aren’t found on the object directly. This also means that you can change the method definitions on a single object if you wish:
b = Account:new { balance = 0 }
function b:withdraw (amt)
-- no limit!
end
function b:getBalance()
return 100000.00
end
b:withdraw(10000.00)
print(b:getBalance())
This concept, of an object having no class, and objects’ behavior being entirely mutable at runtime, is core to understanding JavaScript, but Lua’s syntax is just different enough to keep the C#/C++/Java developer from thinking that she’s on familiar ground.
Hosting Lua
It’s a simple matter to create a C# (or VB, but sorry VB’ers, some habits are just too hard to break) project and add the LuaInterface assemblies to the project. Specifically, both of the assemblies in the “Built” directory-lua51.dll and LuaInterface.dll-are required. The Lua interpreter is entirely compiled into managed code, so both are standard .NET IL assemblies, and thus there’s no weird security permissions So, after doing the “Add Reference” thing in Visual Studio, try this:
using System;
using LuaInterface;
namespace LuaHost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("LuaHost v0.1");
var lua = new Lua();
lua.DoString("io.write(\"Hello, world,"+
"from \",_VERSION,\"!\\n\")");
}
}
}
As you might well infer, this is essentially a hard-wired version of what we did at the command-line a few minutes ago: greet the world from Lua.
Having gotten this far, it’s fairly easy to see how this could be expanded: one thought would be to create a REPL (Read-Eval-Print-Loop, an interactive console) that reads a line from the user, feeds it to Lua, repeat, and host that from within WinForms or WPF. Or even Visual Studio. (Which Microsoft already did, all you WoW players out there.)
If you’re a Web developer, write an ASP.NET handler that executes Lua on the server, a la Node, but using a language that was actually designed, instead of cobbled together over a weekend.
Prolog
Most of the time when we’re writing code for a customer, we expect the customer to tell us how to get things done. There are some projects, however, where the customer doesn’t exactly know the right answer ahead of time-which makes it hard to know if the code is generating the right answer.
Consider, for example, Sudoku puzzles. The puzzle always has an answer (assuming it’s a legitimate puzzle, of course), and we have ways of verifying if a potential answer is correct, but neither the developer nor the customer (the Sudoku player) has that answer in front of them.
(If this seems like a spurious example, then consider certain kinds of simulations or forecasting or other data-analysis kinds of work. At least with Sudoku we know we have one and only one right answer, so let’s work with that for now.)
While writing a Sudoku solver in C# can be done, back in the AI research days, Prolog was developed to do precisely this kind of thing: take “facts” asserted into the system, and when asked to examine an assertion, determine whether that assertion could be true given the facts present within the system.
If that sounded like gibberish, stay with me for a second. Examples will help.
Getting Started with Prolog
First things first: we need a Prolog implementation, and fortunately there’s one written in .NET (and thus easily hostable!). Prolog.NET is available at http://prolog.codeplex.com. Go grab it, install it, and fire up the Prolog.NET Workbench.
(Just for the record, there’s a second “Prolog.NET” implementation at http://prolog.hodroj.net/, which appears to be slightly newer, appears to work with Mono, and appears to have a similar kind of feature set as the CodePlex project version; I chose to use the first one, but I suspect either one would work just as well in practice.)
Writing Prolog
In the “Command” pane of the Workbench, type in the following snippet of Prolog, making sure to include the period (which is a statement terminator, like the “;” in C#/Java/C++) at the end, then click “Execute” at the bottom of that pane:
likes(john,mary).
This line says that “john likes mary”, and Prolog accepts that into the system by responding with “Success” in the Transcript pane above the Command pane. This line, in Prolog terminology, is a fact.
(Well, to Prolog it’s a fact-to Mary it may be an unfortunate situation resulting from having made eye contact with a smarmy co-worker.)
We can assert other kinds of facts into Prolog; in fact, we can assert lots of different kinds of facts, because Prolog knows nothing about the meaning behind the words “john”, “mary” or “likes”, only that A and B are linked by C. So additional facts might look like:
likes(ted,macallan25).
likes(jess,macallan25).
likes(miguel,macallan25).
likes(charlotte,redwine).
valuable(gold).
female(jess).
female(charlotte).
male(ted).
male(miguel).
gives(ted,redwine,charlotte).
These facts tell us that Ted, Jess and Miguel like macallan25 while Charlotte likes redwine, gold is valuable, Charlotte and Jess are female while Miguel and Ted are male, and Ted gives redwine to Charlotte (probably to impress her on a date or something). These facts collectively form a database in Prolog, and, like the more familiar relational form, the Prolog database allows us to issue queries against it:
:- likes(ted, macallan25).
To Prolog, this is a question: does Ted like Macallan 25? Very much so, yes, and it turns out that Prolog agrees-it will respond with a “yes” or “success” response, depending on the Prolog implementation you’re using.
In this particular case, Prolog is looking at the “verb” (“likes”) joining the two “nouns” (“ted” and “macallan25”, what Prolog calls “objects”), and determining if there is an V/N1/N2 pairing in the facts database-and, as we saw earlier, there is, so it responds with a success response. But if we ask it a different query:
:- likes(ted, redwine).
Prolog will respond with a “no” or “failure”. Which totally isn’t true, but Prolog only knows about the facts that were asserted into its database; if it’s not in the database, then to Prolog it doesn’t exist.
Prolog will also allow you to put variables instead of objects into the query, and let Prolog fill the variable with the objects that match:
:- likes(Person, macallan25).
Here, Prolog knows that “Person” is a variable because it starts with a capital letter. (Yes, seriously. Prolog is that case-sensitive.) And it responds by telling us every object that “likes” “macallan25”, which in this case is three objects, “miguel”, “ted” and “jess”.
Now, suppose that Ted likes anyone that is female and who in turn likes a particular kind of beverage. (Ed. note: Meaning, Ted likes a Person who is female that likes a particular beverage. Jess works because she is female (first clause) and because she likes the Beverage Ted passed in (Scotch).) We can express this in Prolog as a rule:
likes(ted,Person,Beverage) :-
female(Person),
likes(Person,Beverage).
Now we present it with the query, who does Ted like that likes Macallan 25?
:- likes(ted, Person, macallan25).
Prolog comes back, correctly, with the answer “jess”.
Prolog is, very simply, an inference engine, and it shares a lot of similarities to rules engines like Drools.NET or iLOG Rules-but in a language syntax, and something that we can call from .NET code.
If these seem like simplistic scenarios, consider a trickier one: a fast-food restaurant chain needs a software system to help them manage employee schedules. Anyone who’s ever worked as a manager of a restaurant (or assistant manager, when the manager decided to “delegate” that job to his high-school assistant manager “to teach a sense of responsibility”, and of course it had nothing to do with his absolute loathing of the task, not that I’m still bitter or anything) knows what a pain it is. Every employee has immutable schedule restrictions, particularly in a college town where schedules change with every quarter or semester, not to mention the complications around seniority and the implicit “more senior people get first pick at the schedule” and so on.
This is exactly the kind of problem that Prolog excels at-we can assert each employee’s schedule restrictions and preferences as facts, set up some rules about how often they can work (no back-to-back shifts, for example), and then let Prolog figure out the permutations of the schedule for final human approval. In fact, Prolog.NET has a sample along these lines (Listing 1).
Walking through all of this is a bit beyond the scope of this article, but the code starts with some declarations of the days of the week, the shifts in the plant, and a definition that a “WorkPeriod” is a given shift/day combination. Then we get into the employee/shift combinations (a shiftAssignment) and the employee/day combinations (a dayAssignment), and finish with a declaration of rules that create the three-way binding between an employee, a shift, and a day to create a given schedule. It’s a great non-trivial example to have a look at, plus it demonstrates the intersection of Prolog and .NET, since the sample itself is compiled into a small WPF app displaying the schedule permutations in a grid.
Hosting Prolog.NET
Like the LuaInterface situation earlier, hosting the Prolog.NET implementation is pretty straightforward (Listing 2). In a C# project, add the “Prolog.dll” assembly, found in the root of the Prolog.NET installation directory, to your project. Obtain a Prolog.Program instance, and use the Parser found in the Prolog namespace to capture Prolog facts and rules and define queries to be run against them.
As you can see, facts and queries are parsed separately and added to the PrologMachine instance, and then executed. The API permits execution in a single-step fashion, allowing for on-the-fly examination of the machine during its processing, but for non-debugging scenarios, RunToSuccess() is the preferred approach.
Another Prolog
Another approach to Prolog-on-the-CLR is that taken by P#, a Prolog “source-to-source” translator that takes Prolog input and generates C# files that can be compiled into your assembly. You can find it at http://www.dcs.ed.ac.uk/home/jjc/psharp/psharp-1.1.3/dlpsharp.html if you are interested.
Scheme
No conversation on dynamic languages can be called complete without a nod and a tip of the hat to one of the granddaddies of all languages, Lisp, and its Emacs-hosted cousin, Scheme. Scheme, like Lisp, is conceptually a very simple language (“Everything is a list!”) with some very mind-blowing concepts to the programmer who hasn’t wandered outside of Visual Studio much. (Code is data! Data is code!)
Scheme, as they say, is a Lisp, which means that it syntactically follows many of the same conventions that Lisp does-all program statements are in lists, bounded by parentheses, giving Scheme code the chance to either interpret the list as a method call or command, or do some processing on the list before passing it elsewhere to be operated upon. It is this “meta” facility that lends Lisps (and, therefore, Scheme) much of the power that is commonly ascribed to the languages within this family.
Getting Started with Scheme
Like the other two languages we’ve seen so far, an implementation of Scheme designed specifically for the CLR-or, to be more precise, the Dynamic Language Runtime (DLR) that runs on top of the CLR and serves as the core for IronPython, IronRuby and the “dynamic” keyword in C# 4.0-is available. Not surprisingly, it is called “IronScheme” and it is available for download on Codeplex at http://ironscheme.codeplex.com in either source or precompiled binary form. Pull it down, install (or build) it, and fire up the IronScheme REPL to get a prompt to play with.
Writing Scheme
As already mentioned, everything in Lisp is a list, so all programming in Scheme will basically be putting together ()-bracketed lists of things, typically in a Polish-notation fashion. So, for example, typing the following:
> (* 5 20)
Yields a response of “100” because that is what applying the “*” (multiplication) function on arguments of “5” and “20” produces.
This list-based syntax alone is fascinating because it means that Scheme can write functions that accept a varying number of parameters without significant difficulty (what the academics sometimes refer to as “flexible arity”), meaning that we can also write:
> (* 5 20 20)
And get back “2000”.
Of course, if all we wanted was a reverse-reverse-Polish calculator, we’d ask some long-haired dude whose family name used to be “Niewardowski” to recite multiplication tables while walking backwards. Scheme also allows you to store values in named storage using (define):
> (define pi 3.14159)
> (define radius 10)
> (* pi (* radius radius))
(define) isn’t limited to just defining variables; we can also (define) new functions, like so:
> (define (square x) (* x x))
> (* pi (square radius))
One of the things apparent when we look at Scheme code is that the distinctions between “variables” and “methods” are quite fuzzy when compared against languages like C# and VB. Is “pi” a function that returns a value, or is it a variable storing a value? And, quite honestly, do we care? Should we? (You might, but you shouldn’t. Unlearn, young Jedi, unlearn.)
Hosting Scheme
If there’s a theme to this article, it’s that hosting language “X” is pretty easy, and IronScheme really is no different. From a new C# Console project, add three assembly references from the IronScheme root directory: Microsoft.Scripting.dll (the DLR), IronScheme.dll, and IronScheme.Closures.dll. See Listing 3.
As you can see, getting an IronScheme engine up and running is pretty straightforward: just ask the DLR’s ScriptDomainManager to give you an IronScheme engine instance. Once there, we only need to pass the Scheme expressions in, and IronScheme will hand back the results. If those expressions resolve into functions, such as in the case above with foo, then we need only cast them to Callable instances, and we can call through to them with no difficulty.
Oh, and for the record? IronScheme is ridiculously easy to get started using on a Web MVC project, because the IronScheme authors have already built the necessary hooks (and Visual Studio integration!) to create an MVC application. In the IronScheme implementation, check out the “websample” directory, which contains a couple of different samples (as well as the IronScheme documentation). Configure an ASP.NET site around that directory, then hit it with an HTTP request of “/blog”, and explore the 100% IronScheme-written blog engine. Admittedly, it’s pretty tiny, but then again, so is the code. And the IronScheme way to represent an HTML view isn’t all that hard to read, either (Listing 4).
Although it may look a little overwhelming, when you peer into it, a number of things leap out: there is a correlation between HTML tags and Scheme functions (“(h2 ...)”, “(form ...)”, and so on), and the open-ended nature of Scheme lists makes it easy to extend the language to incorporate templatized elements into the rendered HTML.
For example, consider this snippet from the above:
`(div ,@(map display-entry blogdata))
This looks pretty innocuous, but here the power of Scheme’s functional nature kicks in-we use the “map” function to take a function, display-entry, and map it over every element in the blogdata collection, which effectively iterates through the collection and generates the HTML for each entry. To those willing to look past the arcane ()-based syntax, Scheme offers all the power of a functional language, combined with the flexibility of a dynamic one.
Is this likely to take over from ASP.NET MVC written in C# or VB any time soon? Maybe not, but long-time practitioners of Lisp and Scheme have often touted how easy it is to get things done in these languages thanks to the ability to build abstractions on top of abstractions, so maybe it’s worth a research spike for a while, just to see.
Clojure-CLR
No discussions of a modern Lisp would be complete without mentioning Clojure, a Lisp originally born on the JVM, but since ported to the CLR. Clojure is a Lisp, but it’s not Common Lisp or Scheme. Its creator, Rich Hickey, put some fascinating ideas about state and data into the language, making it a powerful tool for doing things in parallel. If you’re a Java programmer, picking up Clojure is a highly-recommended step to take; if you’re a .NET programmer, however, although still recommended, it’s not quite as easy, owing to the fact that all of the documentation and articles and books on Clojure are focused specifically on the JVM and Java APIs.
Still, for those willing to brace themselves for a little rough sailing at first, Clojure-CLR can be a powerful experiment, and it’s a natural complement to learning IronScheme. Clojure, unlike most Lisps, has no interpreter, meaning that Clojure-CLR is going to compile everything into IL, and thus eliminate concerns around the “hideous performance” of being an interpreted language.
Moving On
Certainly the crop of .NET languages doesn’t end here. In fact, trying to trim the list down from all the languages I could have discussed was one of the hardest things about writing this article-languages like Cobra, Nemerle, Boo and the aforementioned IronPython and IronRuby, all are powerful and useful languages that can significantly change the development arc of a project if used correctly.
No one language is going to be the silver bullet to all your development ills; what we gain in using a dynamic language, we lose in taking on some of the risks inherent in that language. For example, almost every Ruby developer I’ve ever talked to makes it very clear that in a Ruby project, unit tests are not just a nice-to-have, but an essential necessity to ensuring the project succeeds. The language offers a tremendous amount of flexibility, but at a price.
At the end of the day, that’s probably something that should be said about all the tools we use. Caveat emptor.