Seven More Languages in Seven Weeks: Julia

Julia feels…rough.

There are parts I absolutely love, like the strong typing, the baked-in matrix operations, and the support for multi-type dispatch.

Then there’s the pieces that seem incomplete. Like the documentation, which is very extensive, but proved useless when trying to find out the proper way to build dictionaries in the latest version. Or the package system, which will install things right into a running repl (cool!) but does it without getting your permission for all its dependencies (boo).

All in all, I’d like to build something more extensive in Julia. Preferably something ML-related, that I might normally build in Python.

Day One

  • can install with brew
  • book written for 0.3, newest version is 0.5
  • has a repl built in ­čÖé
  • typeof for types
  • “” for strings, ” only for single-chars
  • // when you want to divide and leave it divided (no float, keep the fraction)
  • has symbols
  • arrays are typed, but can contain more than one type (will switch from char to any, for example)
  • commas are required for lists, arrays, etc (boo)
  • tuples: fixed sized bags of values, typed according to what they hold
  • arrays carry around their dimensionality (will be important for matrix-type ops later on)
  • has dictionaries as well
  • hmm: typeof({:foo => 5}) -> vector syntax is discontinued
  • Dicts have to be explicitly built now: Dict(:foo => 5) is the equivalent
  • XOR operator with $
  • bits to see the binary of a value
  • can assign to multiple variables at once with commas (like python)
  • trying to access an undefined key in a dict throws an error
  • in can check membership of arrays or iterators, but not dictionaries
  • but: can check for key and value in dict using in + pair of key, value: in(:a => 1, explicit)
  • book’s syntax of using tuple for the search is incorrect
  • julia docs are really…not helpful :/
  • book’s syntax for set construction is also wrong
  • nothing in the online docs to correct it
  • (of course, nothing in the online docs to correct my Dict construction syntax, either)
  • can construct Set with: Set([1, 2, 3])
  • arrays are typed (Any for multiple types)
  • array indexes start at 1, not 0 (!) [follows math here]
  • array slices include the ending index
  • can mutate index by assigning to existing index, but assigning to non-existing index doesn’t append to the array, throws error
  • array notation is row, column
  • * will do matrix multiplication (means # of rows of first has to match # of columns of second)
  • regular element-wise multiplication needs .*
  • need a transpose? just add ‘
  • very much like linear algebra; baked-in
  • dictionaries are typed, will throw error if you try to add key/value to them that doesn’t match the types it was created with
  • BUT: can merge a dict with a dict with different types, creates a new dict with Any to hold the differing types (keys or values)

Day Two

  • if..elseif…end
  • if check has┬áto be a boolean; won’t coerce strings, non-boolean values to booleans (nice)
  • reference vars inside of strings with $ prefix: println(“$a”)
  • has user-defined types
  • can add type constraints to user-defined type fields
  • automatically gets constructor fn with the same name as the type and arguments, one per field
  • subtype only one level
  • abstract types are just ways to group other types
  • no more super(), use supertype() -> suggested by compiler error message, which is nice
  • functions return value of last expression
  • … to get a collection of args
  • +(1, 2) -> yields 3, operators can be used as prefix functions
  • … will expand collection into arguments for a function
  • will dispatch function calls based on the types of all┬áthe arguments
  • type on pg 208: int() doesn’t exist, it’s Int()
  • WARNING: Base.ASCIIString is deprecated, use String instead.
  • no need to extend protocols or objects, classes, etc to add new functions for dispatching on core types: can just define the new functions, wherever you like, julia will dispatch appropriately
  • avoids problem with clojure defmulti’s, where you have to bring in the parent lib all the time
  • julia has erlang-like processes and message-passing to handle concurrency
  • WARNING: remotecall(id::Integer,f::Function,args…) is deprecated, use remotecall(f,id::Integer,args…) instead.
  • (remotecall arg order has changed)
  • randbool -> NOPE, try rand(Bool)
  • looks like there’s some overhead in using processes for the first time; pflip_coins times are double the non-parallel version at first, then are reliably twice as fast
  • julia founders answered the interview questions as one voice, with no distinction between them
  • whole section in the julia manual for parallel computing

Day Three

  • macros are based off of lisp’s (!)
  • quote with :
  • names fn no longer exists (for the Expr type, just fine for the Module type)
  • use fieldnames instead
  • unquote -> $
  • invoke macro with @ followed by the args
  • Pkg.add() will fetch directly into a running repl
  • hmm…installs homebrew without checking if it’s on your system already, or if you have it somewhere else
  • also doesn’t *ask* if it’s ok to install homebrew
  • not cool, julia, not cool
  • even then, not all dependencies installed at the time…still needed QuartzIO to display an image
  • view not defined
  • ImageView.view -> deprecated
  • imgshow does nothing
  • docs don’t help
  • hmm…restarting repl seems to have fixed it…window is hidden behind others
  • img no longer has data attribute, is just the pixels now
  • rounding errors means pixels != pixels2
  • ifloor -> floor(Int64, val) now
  • works!

Trust is Critical to Building Software

So much of software engineering is built on trust.

I have to trust that the other engineers on my team will pull me back from the brink if i start to spend too much time chasing down a bug. I have to trust that they’ll catch the flaws in my code during code review, and show me how to do it better. When reviewing their code, at some point I have to trust that they’ve at least tested things locally, and written something that works, even if doesn’t work well.

Beyond my team, I have to trust the marketing and sales folks to bring in new customers so we can grow the company. I’ve got to trust the customer support team to keep our current customers happy, and to report bugs they discover that I need to fix. I have to trust the product guys to know what features the customer wants next, so we don’t waste our time building things nobody needs.

And every time I use test fixture someone else wrote, I’m trusting the engineers that worked here in the past. When I push new code, I’m trusting our CI builds to run the tests properly and catch anything that might have broken. By trusting those tests, I’m trusting everyone that wrote them, too.

Every new line of code I write, every test I create, adds to that chain of trust, and brings me into it. As an engineer, I strive to be worthy of that trust, to build software that is a help, and not a burden, to those that rely on it.

Building a Bridge with Scrum

If you built a river bridge with Scrum:

The roadway would be built first, because that’s the Product Owner’s highest priority. Unfortunately, it would sink to the bottom of the river once deployed. This experience would be called “learning from failure.”

Realizing they needed to get above the waterline using some supports, the team would build a short set of pillars on top of the sunken roadway. The pillars wouldn’t reach above the waterline, but they would be valuable for the experience in building support pillars for this particular river.

Once the first set of pillars had been sunk, the team would use their new knowledge to build a second set of pillars that just breached the waterline, and construct┬áa second roadway on top of that. This would make the Product Owner very happy, because “customers could use it” for the first time.

After the first week, they’d realize they’d built a leaky dam, not a bridge, and that all boat traffic was being blocked.

Working seven days a week, 14 hours a day, the team would scramble to fix the bridge. They’d cut channels in the roadway to let some boat traffic through, then build a third set of supports and a third roadway at the proper height.

Burnt out and frazzled, the team would begin pointing fingers, each specialty blaming the other for the death march at the end. Half would quit, and join a different company, building high rises. The other half would struggle to support the many bugs still left in the bridge, despite not having any experience with the things built by the members who’d left (what was the special concrete mix Nancy used?).

Meanwhile, the Product Owner would be praised for pulling off a miracle, and be put in charge of another bridge-building project.

Three years later, the whole thing would be bulldozed to make room for a ferry.