One of my friends was thinking about Wren earlier in the year to run scripts in a game engine. It was created by Bob Nystrom who wrote Game Programming Patterns which I reviewed earlier. I thought Wren looked interesting so it went on my list of topics to explore.
The language
It describes itself:
Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a familiar, modern syntax.
Alongside the summary:
- Small with the virtual machine at only “4,000 semicolons”.
- Fast single-pass compiler with tight bytecode.
- Class-based from the ground up.
- Concurrent with lightweight fibres.
And looks like this:
System.print("Hello, world!") class Wren { flyTo(city) { System.print("Flying to %(city)") } } var adjectives = Fiber.new { ["small", "clean", "fast"].each {|word| Fiber.yield(word) } } while (!adjectives.isDone) System.print(adjectives.call())
I’ve read over the guides and it comes out as a mostly vanilla scripting language. I don’t mean that as a slight. If you understand C-style object-oriented languages then you should get to grips with it very fast. The documentation is easy to read, I went through it in a couple of sessions.
We’ll rush through the documentation:
- Comments: single line, multiline, nestable
- Identifiers: initial underscore used to indicate class fields
- Newlines: separate statements
- Blocks: curly braces
- Immutable values:
Bool
,Num
,String
,Range
,Null
- Mutable values:
List
,Map
- Methods: object-based, class-based, overloadable by arity, getters, setters
- Control flow:
if
,while
,for
over range, short-circuit logic operators - Variables: true block scope
- Functions: separate from methods, quick syntax for passing blocks to functions
- Classes: methods, getters, setters, operator overloading, implicit
this
, named constructors, private fields, static fields, inheritance does not include static methods or constructors, invoking parent’s methods, class and method attributes - Concurrency: fibres with invoke and yield, can be used for runtime error handling
- Embedding: include as static / dynamic library or directly as source, exchanging data with VM, calling the VM
It’s all pretty nice, either as expected or easily learned. Building it as object-oriented from the start gives it a consistency that some language lack. Personally I prefer statically to dynamically typed languages but for small tasks it doesn’t matter as much. Normally I dislike using just an underscore to indicate class fields but that’s partly because it gets used for so many other things. If it’s mandated in the language it should give consistency. Method overloading isn’t essential but it’s nice to see. The syntactic sugar for passing blocks to functions would be interesting to use. Building the virtual machine into an existing system is easy although passing data back and forth looks fiddly but not hard. That said people have already gone out and made some bindings already. It feels like a scripting language that hasn’t scrimped on the details.
How to choose
I like the look of Wren but is it the right choice? This is purely hypothetical for me as I don’t need a scripting language right now but having to choose tools, libraries or system is a fairly common problem.
With a brief search I was able to find a long list of embedded scripting languages. It includes Wren but many others, names I recognise and ones I don’t. I heard of Lua as an embeddable scripting language years ago, there are 10 different projects for that in the list. I associate JavaScript with browsers and there are another 10 more projects here. There are big name languages, sometimes cut down for scripting: Ada, C, Java, Pascal, PHP, Python and Ruby. There are names I don’t recognise: Anko, Berry, Dhall, Gluon, Janet, Red, Squirrel and Toy. Many many options to research. It’s not just languages where you find lots of options. I mentioned JSON parsers recently and found a list of 43 of them. How do you make a choice?
First ask what you’re really trying to do. If you want to include an embedded scripting language in your game engine then, maybe, you want entities within your game to have flexible behaviours. Maybe you that don’t want to recompile the code after every design change. Maybe it’s going to be part of the game itself. Who is going to be writing these scripts? Is it coders, designers, artists or the players themselves. Do you expect them to be familiar with programming languages or completely unfamiliar? Will they be willing to take time to learn or does the language have to be understandable. There is a gamut of languages including visual ones or esoteric ones. You’ll probably know roughly what you want but it doesn’t hurt to formalise it. If you don’t have specifics for some areas that’s fine, just keep what you do have in mind.
Some of these things might be non-negotiable and that could easily be price or licencing arrangements. For an individual you might not have the money to shell out for a library. For a company it’s more likely to be possible but they might not be willing, there’s not a budget for it. Companies tend to have core products they work on and their developers will have expertise in those. If you’re looking at implementing a language or a library outside of that it’s good to at least consider a purchase. Developer time isn’t free and creating something in house takes time to start with and then has to be maintained afterwards. On the other hand the right licence might get you software for free but come with strings attached. Any sort of copyleft licence is probably no go for a commercial product. However there are a great many sorts of licences and we should be thankful for that. If your company doesn’t already have a policy for these it should get one. Ideally a list of acceptable licences a developer can use without further investigation and methods for fulfilling the terms of those licences. Often that’s just releasing the licence alongside the finished software.
The implementation language may or may not be a barrier to a library. Unless you’re getting a pre-built library I’d certainly prefer something I’m familiar with. If you’re having to debug issues being able to get in there and see what’s happening is useful. On the other hand you could treat it as a black box, that’s probably what you’ll have to do if it’s a commercial product. It might matter how hard it’s going to be to integrate into your build system. With some that can be fairly simple. I’ve been doing a lot of work with vcpkg recently that allows you to build packages locally and then cache them for later. Once it’s in place that can mean only a few lines to integrate a new package. As it happens Wren is available on there, so is Lua. Another alternative is cmake and it’s ExternalProject which is a bit longer but more easily customisable.
For many companies it might matter how much support the library will have. Some projects will be under active development, some might only be getting occasional bug fixes, and some haven’t been updated in a decade. It certainly can be a risk if their might be bugs but further development is unlikely. With an open source project you can always go in and try and fix it yourself but that means time and effort. With a closed source product then you can’t see the code but, hopefully, the sellers will be able to provide support. Such support might not be immediate so you could be left having to work around problems. If you can find a open source project that’s under active development, ideally with multiple contributors, that is probably best.
So far these are all fairly large scale considerations. That means you can, say, go through a big list of embedded scripting languages and throw out those that are obviously unsuited for the job. Once you’ve done that you’re left with a list of candidates. It’s time to metaphorically roll up your sleeves and go through them one by one. If there are a lot of them you should probably try and get a rough impression to prioritise further investigation. When you have a smaller number there is definitely going to be further reading. You might want to try building or integrating things to see how it goes.
This can be tricky. How much time do you spend? The more you investigate each library, or language, the better idea whether it will suit your purposes. On the other hand all that is time and effort. It could be that you don’t need a perfect system. If I were looking for another JSON parser I would:
- Check the licencing to make sure it’s acceptable.
- See if the API looks okay.
- Make sure it builds.
- Try integrating it and see what happens.
In the end
If you want to decide to use Wren, Lua or Moonscript you’re going to have decide for yourself. I think it looks nice but that’s just me. Meanwhile I’m wondering what unit testing framework is best. I’ve used GoogleTest, Boost Test, unittest-cpp and Catch2. There are undoubtedly more out there, looks like it. I’ve got some reading to do.
Leave a Reply