Nearly a year ago I wrote about using the J programming language to write a Mandelbrot fractal renderer. I proudly exclaimed that J could be used to “write out expressions like we’d write English sentences,” and immediately proceeded to write a nonsensical, overcomplicated solution.

My final solution bit off more than it needed to chew. The next verb we wrote both calculated the next value of iterating on the Mandelbrot formula and also managed appending that value to a list of previously calculated values.

I nonchalantly explained:

This expression is saying that next “is” (=:) the “first element of the array” ({.) “plus” (+) the “square of the last element of the array” (*:@:{:). That last verb combines the “square” (*:) and “last” ({:) verbs together with the “at” (@:) adverb.

Flows off the tongue, right?

My time spent using J to solve last year’s Advent of Code challenges has shown me that a much simpler solution exists, and it can flow out of you in a fluent way if you just stop fighting the language and relax a little.

Let’s refresh ourselves on Mandelbrot fractals before we dive in. The heart of the Mandelbrot fractal is this iterative equation:

The Mandelbrot set equation.

In English, the next value of z is some constant, c, plus the square of our previous value of z. To render a picture of the Mandelbrot fractal, we map some section of the complex plane onto the screen, so that every pixel maps to some value of c. We iterate on this equation until we decide that the values being calculated either remain small, or diverge to infinity. Every value of c that doesn’t diverge is part of the Mandelbrot set.

But let’s back up. We just said that “the next value of z is some constant, c, plus the square of our previous value of z”.

We can write that in J:


And we can plug in example values for c (0.2j0.2) and z (0):

   0.2j0.2 (+*:) 0

Our next value of z is c (0.2j0.2) plus (+) the square (*:) of our previous value of z (0). Easy!

My previous solution built up an array of our iterated values of z by manually pulling c and previously iterated values off of the array and pushing new values onto the end. Is there a better way?

Absolutely. If I had read the documentation on the “power” verb (^:), I would have noticed that “boxing” (<) the number of times we want to apply our verb will return an array filled with the results of every intermediate application.

Put simply, we can repeatedly apply our iterator like so:

   0.2j0.2 (+*:)^:(<5) 0
0 0.2j0.2 0.2j0.28 0.1616j0.312 0.128771j0.300838

Lastly, it’s conceivable that we might want to switch the order of our inputs. Currently, our value for c is on the left and our initial value of z is on the right. If we’re applying this verb to an array of c values, we’d probably want c to be the right-hand argument and our initial z value to be a bound left-hand argument.

That’s a simple fix thanks to the “passive” verb (~):

   0 (+*:)^:(<5)~ 0.2j0.2
0 0.2j0.2 0.2j0.28 0.1616j0.312 0.128771j0.300838

We can even plot our iterations to make sure that everything looks as we’d expect.

Our plotted iteration for a C value of 0.2 + 0.2i.

I’m not going to lie and claim that J is an elegantly ergonomic language. In truth, it’s a weird one. But as I use J more and more, I’m finding that it has a certain charm. I’ll often be implementing some tedious solution for a problem in Javascript or Elixir and find myself fantasizing about how easily I could write an equivalent solution in J.

That said, I definitely haven’t found a shortcut for learning the language. Tricks like “reading and writing J like English” only really work at a hand-wavingly superficial level. I’ve found that learning J really just takes time, and as I spend more time with the language, I can feel myself “settling into it” and its unique ways of looking at computation.

If you’re interested in learning J, check out my previous articles on the subject and be sure to visit the JSoftware home page for books, guides, and documentation.