Goodness in programming languages, part 3 – not doing the same thing more than once

Posts in this series: Syntax, Deployment, Metaprogramming, Ownership

I’m going to use a word here – don’t stop reading: Metaprogramming. Does the language provide what you need to avoid repeating yourself?

Repeating boilerplate code, algorithms and most importantly ideas, slows you down, makes maintenance difficult, and allows all kinds of mistakes to creep in. If a language provides the ability to abstract, name and re-use all the different types of structure it contains, you can avoid harmful repetition.

Here are some things I like:

  • Python, JavaScript and Scheme’s ability to treat functions like any other object. A massive step towards sharing code is being allowed to pass around something that can be called without worrying about what it is.
  • Scheme’s ability to define an algorithm independently of types. In Scheme, there is never a need to write another version of the same function because it deals with different types of thing.
  • Python’s ability to read and modify classes just like any other object. Want a class just like your current one, except it logs every method call? Write a function that copies and modifies the class definition.
  • Scheme’s ability write code about code. In Scheme, code is just some nested lists. It’s trivial to build and modify code without stepping out of the language.
  • C++’s ability to write code that runs at compile time. If you can stand the syntax and (lack of) debugging, C++ template metaprogramming allows you to build C++ code at compile time without stepping out of the compiler environment.
  • Scheme and C’s macro systems. Both Scheme and C (and C++) allow you to write macros that build commonly-repeated code. Scheme’s syntax for this is much easier to work with.

Until you’ve experienced the freedom of totally generic code in a language like Scheme it’s hard to explain why the “Generics” features of some languages are so lacking. Of course, static typed languages work under different constraints. Would it be possible to write a language with very strong generic programming features, but which still allows static typing and compiling to native, non-generic code? I think so.

Scheme 7: Macros video

Series: Feel the cool, Basics, Closures, Recursion, Quotation, Lambda, Macros.

Continuing the series on Scheme, this video explains the ultimate alternative – when nothing else is flexible enough, we can create our own bits of lanugage using macros.

Slides for Scheme 7: Macros

Goodness in programming languages, part 2 – getting your code running

Posts in this series: Syntax, Deployment, Metaprogramming, Ownership

The fancy word for what I’m talking about here is Deployment. How easy is it, once you’ve written your code, to get it running on someone else’s computer? What barriers are there to someone else using your program?

Examples of potential barriers include:

  • Having to download some other program first, e.g. a runtime or some kind of dependency.
  • The actual program being a huge download.
  • Something mysteriously not working because of different versions of something on the person’s computer.
  • The program simply not working on the operating system or machine architecture of the computer.

Anything that can be done to remove these barriers makes my life as the supporter of the program easier, and makes it more likely people will use it.

Here are some things I like:

  • Java’s ability to run almost anywhere. Once you have the runtime, Java code is relatively easy to get running on many different operating systems and architectures, using almost-identical code. Other runtime-based languages are also strong here.
  • Java and Python’s large built-in libraries. Both Java and Python include large amounts of functionality in their standard libraries, reducing the need to depend on third-party components.
  • Python and Perl’s ability to work out of the box on most Linux systems. If you are developing for Linux, you can pretty much guarantee that an up-to-date runtime will be available, meaning no dependencies at all are needed.
  • Many languages’ easy integration with Linux packaging. Most of the above barriers disappear if you can install dependencies using your operating system’s built-in package manager.
  • Quickly‘s easy way to build your program into the packaging system. Things really become easy if your program itself is integrated into the packaging system.
  • C and C++’s lack of dependencies. It is possible to write C and C++ programs that depend on nothing except standard runtime libraries, which are almost guaranteed to exist on most machines.

One way to handle dependencies is to package them together with your code. This is what most corporate Java software does – the specific Java runtime that is known to work is packaged with the program itself. This makes for big downloads, and defeats the concept of providing a single package for all platforms, but it does work. It also makes for huge headaches to do with licensing, and is often impossible for software producers who don’t employ legions of lawyers. It also feels bad and wrong.

When packaging and deploying software, I subscribe to the philosophy of “Find the dependencies – and eliminate them“. Until someone can click a single button and have your software running, you haven’t finished.

Building jEdit from source

I have recently agreed to take over development of the JSLint plugin for my favourite editor, jEdit.

To start developing I decided to build jEdit and its plugins from source, which wasn’t as easy as I would have expected (thanks to deffbeff for some pointers). A few small changes to the setups for the plugins would make it much easier – at some point I may try to help out there, but for now, here is how I built jEdit and the set of plugins I use regularly:

sudo apt-get install openjdk-6-jdk ant git-core subversion

cd ~/code/public
mkdir jedit
cd jedit

svn co https://jedit.svn.sourceforge.net/svnroot/jedit/jEdit/trunk jEdit

cd jEdit; ant; cd ..

mkdir plugins

Now I made a file inside plugins called build.properties which looked like this:

install.dir       = ../../jEdit/build/settings/jars
jedit.plugins.dir = ../../jEdit/build/settings/jars
jedit.install.dir = ../../jEdit/build
build.support     = ../build-support

And then continued like this:

cd plugins
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/build-support/trunk build-support

svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/ErrorList/trunk ErrorList
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/CommonControls/trunk CommonControls
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/InfoViewer/trunk InfoViewer
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/Console/trunk Console
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/BufferList/trunk BufferList
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/FindFile/trunk FindFile
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/GnuRegexp/trunk GnuRegexp
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/OpenIt/trunk OpenIt
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/RecentBufferSwitcher/trunk RecentBufferSwitcher
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/Sessions/trunk Sessions
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/WhiteSpace/trunk WhiteSpace
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/ScriptEnginePlugin/trunk ScriptEnginePlugin
svn co https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/JavascriptScriptEnginePlugin/trunk JavascriptScriptEnginePlugin

git clone git://jedit.git.sourceforge.net/gitroot/jedit/ProjectViewer
git clone git://github.com/andybalaam/jslint-plugin-for-jedit.git jslint

cd ErrorList; ant; cd ..
cd CommonControls; ant; cd ..
cd InfoViewer; ant; cd ..
cd ProjectViewer; ant; cd ..
cd Console; ant; cd ..
cd BufferList; ant; cd ..
cd FindFile; ant; cd ..
cd GnuRegexp; ant; cd ..
cd OpenIt; ant; cd ..
cd RecentBufferSwitcher; ant; cd ..
cd Sessions; ant; cd ..
cd WhiteSpace; ant build; cd ..
cd ScriptEnginePlugin; ant; cd ..
cd JavascriptScriptEnginePlugin; ant; cd ..
cd jslint; ant; cd ..

To find out the dependencies of all plugins and therefore what order to build them, I did this:

find ./ -name "*.props" | xargs grep "depend.*plugin"

Surely something should do this for me automatically?

The problem I haven’t solved yet is that the FTP plugin requires JUnit. I could have copied the junit.jar into the jars dir and I think it would have worked, but I want to do it “properly”…

Finally, I made a .desktop shortcut file in ~/.local/share/applications/jedit.desktop like this:

[Desktop Entry]
Name=jEdit
GenericName=Programmer's Text Editor
Comment=Edit text files
Exec=java -jar /home/andy/code/public/jedit/jEdit/build/jedit.jar -settings=/home/andy/code/public/jedit/jEdit/build/settings %U
Icon=/home/andy/code/public/jedit/jEdit/doc/jedit.png
Terminal=false
Type=Application
Categories=Development;TextEditor;
StartupNotify=true
MimeType=text/plain;
StartupWMClass=org-gjt-sp-jedit-jEdit

Which enabled me to run the jEdit I had built from my system menu.

Note that I am running jEdit under OpenJDK because Sun/Oracle Java is annoying to get hold of at the moment, and generally somewhat evil. Thanks Oracle for killing Java. jEdit does not work brilliantly with OpenJDK, which is frustrating. Maybe I’ll try to fix it?

Entertain your baby using your Android phone

Last night my friend and I uploaded the first version of Baby Distraction, an Android app featuring charming cartoon animals, vibration and sounds.

I helped almost exclusively in an advisory capacity, but still am inexplicably proud of the result: it’s incredibly simple, but polished, and, most importantly, their baby loves it.

This morning I searched for “baby games” on the Android Marketplace, and it was the top hit. Fame and fortune await.