Programming in Julia – the caveats

Not everything in Julia is great, like I’ve said before, there is no definitively perfect programming language. One of the caveats of the language is its size. Much of this size is also what makes it an exceptionally powerful language, so it is a bit of a catch-22. This discussion will concentrate on some of the more global issues.

Documentation

One of the biggest caveats I have encountered with Julia is the vagueness  of some of the documentation. The language itself is seemingly well documented, but does suffer from a lack of examples to illustrate how certain features work. Third party packages are another thing altogether – some seem to suffer from little or no documentation, and one is forced to searching on Stackoverflow for answers. A case in point is the module. Ideally, this is a means of encapsulating a series of related functions, so they can be easily ported. It took me over two hours to finally figure out exactly how they could work. The problem here is one of the language being in flux still, with changes to the syntax being made. Some of these issues may sort themselves out when a stable version is released.

Consistency

Programmers expect consistency. For the longest while I was running the scripts I wrote through the command line:

julia imageIO.jl

Now that worked fine, until I incorporated the use of a plotting function from the packages Gadfly (Julia has no built in visualization functions). It actually could not plot the histogram I wanted it to, so in the end I opened up Julia in interactive mode, and low and behold, it worked. Now Gadfly uses a browser window to display the graphics, which isn’t a problem. But running a script  means the following:

include("imageIO.jl")

Which doesn’t seem as intuitive as it could be. Used in any context the term include, suggests something more akin to how C uses it. Indeed, when I later created a module, it was “included” in another script using:

include("imageENH.jl")
using imageENH

This makes sense, but running a script should probably use something like “run”. Unless of course you are actually including a module in the main interpreter. There is some ambiguity here.

So, there seem to be two ways to write programs : the script, or the module (lets leave out packages for the moment). A script is a simple program which can contain any number of functions, and a “main” portion of the program at the bottom, essentially a script. A module encapsulates a series of functions, for the sake of reusability.

Deprecation

The problem with any new language is that it suffers from instability. Gone are the days when a language was designed in its entirety before it was implemented. Consider Algol as an example of this. The first version, known now as Algol 58 was designed by committee, and implemented in a limited manner. When the committee met in 1960 to consider its deficiencies, the language was redesigned to become Algol 60. It was not common for a language to be used as it was evolving. This is however common now, and Julia is a prime example, although it does lead to issues, one in particular is the idea of deprecation. This is not new of course, new versions of Fortran often deprecated older, obsolete syntax. A case in point is the Julia syntax for selecting only certain elements from an array. This was previous achieved using {a,b, …} which means a statement of the form b[{1,3}] would select the 1st and 3rd element of b. Now this has been deprecated, replaced by Any[a,b, …] or in the case of the example: b[Any[1,3]]. However if the range of indices is stored in an array, this syntax cannot be used, for example if d=[1,3], then choosing the 1st and 3rd elements of b would be performed as b[d]. Deprecation will obviously be less of an issue when the language stabilizes.

Error Messages

I have to say it. The error messages in Julia are less than optimal. Some have to do with runtime issues. For example, consider the following code snippet, which reads in an integer, creates an array of that size, assigns the value 1 to all elements, and attempts to print out element n+1:

print("A number: ")
n = chomp(readline())
n = parse(Int, n)
x = [1:n;]
x[1:end] = 1
println(x[n+1])

Here is the program running, with a BoundsError triggered:

JuliaBoundserror

In another piece of code, which uses = instead of == in a conditional,

print("A number: ")
n = chomp(readline())
n = parse(Int, n)

if n = 1
    println("Why?")
end

the following syntax error is issued:

JuliaSyntaxerror

While the information exists as to the type of error, and where it is, there is also a lot of trace information that may not be that useful to the novice programmer. In fact unlike other languages, error messages are not well localized. In fact they are often quite verbose.

IDIOSYNCRASIES

There are some idiosyncrasies which programmers have to look out for. When dealing with arrays, if an array is created:

arrayA = [1, 2, 3]

and then copied:

arrayB = arrayA

Then any changes made to arrayB will be reflected in arrayA – this is because arrayB is not a copy of arrayA, but merely references it. To make a copy requires the copy function:

arrayB = copy(arrayA)

INSTABILITY

Despite all the best intentions, there are still instabilities in the compiler. These manifest themselves in errors of the following form, which end up crashing the Julia session:

GC error (probable corruption) :
<?#0x10bd930c0::0x0>

signal (6): Abort trap: 6
__pthread_kill at /usr/lib/system/libsystem_kernel.dylib (unknown line)
Abort trap: 6

The same program run again works fine. I can only imagine there are memory issues.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s