About Me
Hello, I am

James Williams

James is a standard issue nerd, practically to a fault. He was learning BASIC while his peers were learning to throw and catch. He enjoys walking around a well-lit 3D-rendered landscape but would prefer to stay indoors. He won't dance (don't ask him) but he will /dance and /manderville all night long. If you're interested in an in-depth analysis between the command techniques of various Starfleet captains, you are going to have a great time with James at parties (this is a lie: James doesn't go to parties).

Professionally, James is a seasoned developer with nearly two decades of experience. He enjoys all sorts of different programming languages, platforms, and programming methodologies. His own personal style is a spicy mix of functional and object-oriented: he even nearly understands monads!

When he's not working, he's probably poking at his personal programming projects. Beyond that: you might find him playing a turn-based RPG (or watching a Let's Play of a more action-oriented RPG), editing pictures in Photoshop, reading a novel with a spaceship on the cover, and always always always drinking far more tea than can possibly be wise.

(The lemur's name is Gary.)

My Recent Activity

Finished Heavensward last night.

That was a good expansion. I might have to NewGame+ it at some point to get the story a little more coherently (and not spread out over several months).

I was extremely disappointed in the final trial, though. I'm not sure what it was like originally, but now it's been nerfed to the point that it's barely a game.

It looked pretty and was great to watch but that just goes to show: it should have been a cut scene. Indeed, a cut scene would have been better because they could have had anime moves and things!

As the final climax of the entire expansion, it really undercut the experience. That said, I'm trying not to let it spoil everything that came before because the rest of it was really quite good.

I wanted to link to that big entry down below but to do that, I needed to add permalinks for microblogs.

That exists now. See?

That last "micro"blog was a doozy. Maybe I don't need to add a "real" blog engine after all.

Since this is my site, the character counter is just a suggestion, after all. Hmm.

One issue that I've had since the beginning was "How do I represent the different item types (book, game, project) in a strongly typed way while also reducing the amount of boilerplate I need?"

In C#, I'd just make some interfaces and an object hierarchy and call it a day. And while one can do that in F#, it's against the spirit of what I'm trying to learn.

I went down a few paths (including some pretty gnarly heroic reflection code, immortalized in this "delete all the old code" commit) but nothing ever really felt right. I ultimately just ended up copy-pasting a bunch of the same code into Book.fs, Game.fs, and Project.fs and moved on.

I've slowly been solving this, starting a couple weeks ago when I added some discriminated unions to represent each type (in this commit). That ended up with a lot of similar code in pattern matching blocks, but I felt okay about it because the compiler was going to help me out by noticing missed patterns.

Then, last weekend, I watched a talk from Mads Torgersen on "The functional journey of C#". He made a point that a big difference between OO and functional programming is that OO lets you put new behaviors in one place (encapsulated in the base class, perhaps) while functional programming makes you spread it out all over the place and duplicate things in each function. But the functional approach is more extensible since all the behavior is out in the open.

He said it better. Go watch the talk.

Anyway, I've taken that to heart and done a great big refactor today.

Before, I really wanted to be able to have a list of, like, FormField<'t> to support things like FormField<string> and FormField<DateTimeOffset> and FormField<string option>.

This is fine as far as it goes but:

  1. You can't put those in the same list because they're all different types
  2. You can't pattern match over the generic type so it's hard to do things with them

This wouldn't have been so bad in C#. I'd just have a non-generic FormField interface or something. I don't know. But in F#, it's kind of a drag.

So I embraced what Mads was saying about duplicating behaviors as needed. I now have a new "FormField" concept where each FormField is a discriminated union of everything that a form field could ever be.

I wrapped up a bunch of pattern matched functions to do things with these and it's kind of annoying but really not that bad. The compiler and tooling helps a lot here.

I'm pretty pleased with it.

I know this is far from perfect and not what an F# master would write.

But I think this is a solid improvement and shows how much I'm growing into this new-to-me language and paradigm.

I can only imagine six months from now when all of this seems really gross to me and I have much better ways to accomplish all of it.

I can't wait.

The infinite boss rush combined with "we'll go into an animation any time you're doing well to make sure that you lose your ATB charges and limit breaks as often as possible" as a hell of a way to design an endgame.

"We like the end of the game to be completely different from the 40 hours that came before so the player is dramatically unprepared. It's like two games in one!" -- Nomura, probably

I might have to put this one down for a few weeks.

The end of chapter 17 and the beginning of chapter 18 is just a non-stop thrill ride with no chance to catch your breath!

Or to save and go do something else.

Which is to say, I've played this for a bit longer than I wanted to play it.

But the end is in sight. My Intergrade experience is almost here.

Finished the Vath quest line.

Still got a fair bit to do for the Vanu Vanu and Moogles. They're never satisfied.

I was very amused that the final Vath quest was "Go talk to the leader" who told me what a great guy I am. Quest complete.