Here is the long overdue story of how I ended up creating Ralph.
After I got my bachelor’s degree in the fall of 2010, I finally had some time to explore mobile application development on iOS and Android. I had a few rough ideas and started implementing them, but soon realized it could not be done as quickly as I had initially hoped.
Mobile application development is a pain
First, I assumed it would be possible to write applications in a common language and share a single code base among both platforms by abstracting away the framework-specific code. However, iOS and Android applications differ significantly in their framework’s language (Java vs. Objective-C), architecture (e.g., lifecycle of screens) and features.
That means code can basically only be shared across platforms by moving it to a native, shared library. As Objective-C is a C superset, calling into a native library is easy, but on Android, calling native functions and exposing Java methods to a native library requires writing additional bridging code using the JNI, which is known to be error-prone.
Second, just implementing simple user interfaces required writing large amounts of Java and Objective-C, and structuring the code in complex and unmaintainable ways. There was just too much boilerplate code that could be abstracted away, and patterns that could be automated (e.g., serialization on Android).
Third, the long edit-compile-and-run cycle reduced productivity significantly. On both platforms, modifying the applications at runtime is not supported directly, which is very unfortunate, as user interface development usually involves quickly prototyping new ideas and iteratively adjusting details.
Interactive development in Lisp is a joy
So an investigation into the possibilities of using a dynamic language which could solve those problems followed. I mainly focused on Lisp dialects, as they commonly have powerful metaprogramming facilities (e.g., macros), and allow interactive development (e.g., through hot code replacement or a REPL).
In the Dylan world, OpenDylan is the only remaining maintained compiler. It does not have a backend that generates native ARM code, but one that generates C, which can be ported to new architectures/platforms with less effort than creating a completely new backend. However, nobody had ported it to iOS or Android yet and my embedded development and compiler knowledge was fairly limited, so porting it would have taken a significant amount of time and effort, and success was uncertain.
In the Common Lisp world, ECL was already ported to iOS and Android, but these ports were unmaintained and it was unclear how to perform interactive development.
In the Scheme world, Gambit-C looked very promising. It could be easily compiled on Android and was used for game development on iOS – interactively using a REPL! However, it only provides a low-level C FFI and was still missing a high-level bridge to each platform’s framework, which again would have required a lot of effort to get working and correct.
ParenScript’s compiler initially worked well for small programs, but I soon ran into problems while working on larger applications. For example, writing macros was prone to errors, as they need to be written in Common Lisp, but generate ParenScript code. Also, I noticed performance problems testing the resulting apps on actual mobile devices.
Ralph to the rescue
After some research, I discovered that an early version of Dylan was much more Scheme-like and its syntax was still based on S-expressions – a perfect fit. As I’m not good at naming things, I simply adopted Apple’s internal code-name for Dylan: Ralph.
Eventually, Hannes convinced me to write up my findings in a paper and submit it to the International Lisp Conference. Luckily, it was accepted and I got to present a couple of slides about it. Last year I didn’t work much on Ralph, as I was busy with my Master’s thesis, but I’m currently trying to revive the project .