Tuesday, October 01, 2019

Gotcha: go Foo().Bar()

To my surprise, but in accordance with the Go language specification, the following code invokes Foo() in the current goroutine and then starts a separate goroutine to invoke Bar():

    go Foo().Bar()


I incorrectly assumed that it created a separate goroutine to evaluate the entire expression.  I'm not sure why I assumed that.  If you want both Foo and Bar to be run inside a new goroutine, you need something like this:

    go func () { Foo().Bar() }()


Hopefully writing this down will help me remember.

Tuesday, September 24, 2019

Review: A Brief History of Time 👍

I've been a fan of theoretical physics for a long time, but had never actually read Dr. Hawking's wildly popular A Brief History of Time. I got a coupon to buy it for $2 and went for it.  Even if you're only interested in science or the history of science, regardless of your own science ability, I'd recommend this book.  It's highly approachable.

The first 80% of the book describes how we came to know what we do know about the universe.  It's amazing how cleverly people can discern truth from a pittance of data available from the stars.

The book paints an informative picture of human nature.  It takes us a long time to embrace the truth when it happens to conflict with our notions of tradition, right, or beauty.  For example, regarding a universe that expands, Hawking writes, "This behavior of the universe could have been predicted from Newton's theory of gravity at any time in the nineteenth, the eighteenth, or even the late seventeenth century.  Yet so strong was the belief in a static universe that it persisted into the early twentieth century."  Humans love to grow attached to ideas, regardless of their truth or utility.  It's cliche that good ideas are initially opposed and discarded, and it's apparently true in the history of cosmology and theoretical physics.

The final 20% of the book describes speculative theories that haven't yet been tested.  This part of the book is not as fun to read. It lacks the anecdotes of creative discovery that make the first part of the book so fun: finding that a theory agrees with natural observation, or making observations that hobble all known theories.  If you want to focus only on the best parts of the book, you can skip chapters 10-12, and perhaps chapter 9.  For that content, your time may be better spent skimming Wikipedia articles about the arrow of time, wormholes, and string theory.

Thursday, August 29, 2019

Review: The Mote in God's Eye 👍

I just finished The Mote in God's Eye by Larry Niven & Jerry Pournelle.  It was excellent.  It's my favorite kind of speculative fiction: imagine one small change to how the world works and then explore its consequences.  In this case, the exploration is packaged as a first contact narrative which makes the comparative anthropology feel natural and entertaining.

Ignoring superficial differences, alien biology deviates from human biology in one way.  That deviation leads to substantial differences in their evolution, societal organization, priorities, and motives.  Niven and Pournelle toss in a few other interesting ideas along the way.

I sometimes had trouble keeping the cast of characters straight.  I've never had a mind for large social networks, so that's probably as much my problem as theirs.  Either way, it didn't detract from the story or the ideas.  It's definitely worth reading.

Monday, August 12, 2019

Databases by code size

I was curious how various databases compare in terms of their total source lines of code.  For each database I cloned the source repository or downloaded a source tarball.  I deleted code related to tests, and producing documentation (some projects have more test code than database code, so this can make a big difference).  Then I ran scc.  The numbers below are what scc labels as Code.  Since the methodology isn't exact, I only retained two significant figures.

The results are sorted from smallest to largest by SLOC count.  Let me know if you find mistakes or want another database included in the results.

Saturday, November 24, 2018

Goodbye phone spam

I've been self-hosting voice calls and SMS for a while now.  Like most Americans, I get a ridiculous number of spam calls.  The main sources of phone spam for me are, in order:

  1. neighbor spoofing
  2. vendors who use my number long after our transaction has completed
  3. calls intended for a former owner of my number
I considered a few options to reduce spam volume.  Since I self-host my phone infrastructure, the following approach was easy to implement and has been really effective:
  • choose two phone numbers in an area code that has never called me before
    • 906 or 308 are good candidates for most people
  • let these numbers simmer for three months
  • give one number only to immediate family ("private" number)
  • give the other number to everyone else ("public" number)
  • block all calls without caller ID
  • block all calls whose caller ID has the same area code as my numbers
  • burn the public number annually
Letting numbers simmer with an intercept message stops a lot of spam in category #3.

Blocking calls from the same area code eliminates category #1 entirely.  Since I use an area code that has never called me legitimately, there are essentially no false positives.  In practice, this also blocks most calls from category #3, so I have belt and suspenders there.

Spam in category #2 is trickier to block since I initially want these vendors to contact me (dentist, mechanic, etc), but want the calls to stop once our working relationship is permanently finished.  Asking nicely works some of the time, but it doesn't help if a vendor sold my number or lost it in a data breach.  Burning my public number annually or biennially eliminates category #2 that can't be handled in another way.

This approach might not work for others, but has proven highly practical for me.

I considered having only a single phone number and using a white list.  Maintaining an accurate white list seemed like too much effort.  I also didn't like the risk of false positives.  For example, if my kids call me from an unexpected number, they should get through immediately.

My private number is essentially a long term token granting access to my attention day or night.  My public number is a short term token granting access during reasonable hours.  For example, when I ask not to be disturbed, my phone infrastructure routes the public number directly to voicemail but still routes the private number to my phone.

Thursday, October 25, 2018

Soylent Eggnog

I usually drink Soylent for 2 meals every day. With the arrival of fall, I'm in the mood for some 'nog. Here's the recipe I use to make a Soylent that tastes pretty darn close to the flavor of eggnog.

Mix up 12 oz of Original Soylent like normal.  Add the following:

  • 3 tsp sugar
  • 1 tsp vanilla extract
  • 1/2 tsp nutmeg
  • 1/4 tsp rum extract
  • pinch of cinnamon

Tuesday, August 14, 2018

4X Solitaire

Ever since Civilization came out, I've enjoyed the 4X game genre.  If I'm in the mood for a simple 4X experience, I'll play Battle of Polytopia with its small map and sparse tech tree.  Sometimes that's even too complex, so I made a solitaire game with a 4X feel.

Setup


Start with a standard deck of cards.  Remove the jokers. Set aside the kings, face up:

Choose any king. This is your king and your suit. Turn this king face down among the other kings. Here I chose the king of diamonds:

 Leave the kings aside and shuffle the rest of the deck.  Deal three cards, face up, next to each other at the edge of the table.  This is your arsenal:

Turn over the king stack onto the deck.  All cards in the deck will be face down except for your king.  I often find it helpful to manually insert the kings into the deck at random locations like this (my king is sticking out to highlight that he remains face up):

Shuffle the deck.  Deal cards, face down, in a 7 by 7 grid. Of course, your king will still be face up:

Play


The 7 by 7 grid is the map.  Face down cards are parts of the map that you haven't discovered yet.  My initial territory is any face up card matching my suit.  When you start, your territory is only a single card; namely, your king.

To win you must discover the entire map and make it your territory. Try to do it in as few turns as you can.  On each turn, you can perform one of the following moves.

Explore


Turn all cards face up which are adjacent to a chosen face card of your suit.  A card that's fully surrounded has 8 adjacent cards.  A card near the edge may have fewer adjacent cards.

Here I've used my first move to explore the map around my king.  I expanded my territory by one square (the 6 of diamonds) and uncovered four squares of enemy territory.

Travel


You can swap a face card of your suit with any other space in your territory.  In the image above, I could move my king to the right by swapping him with the six of diamonds.  You don't have to travel to an adjacent space, that's just how the layout appears in this image.

Capture


You capture a space, making it part of your territory, by attacking it with a card in your arsenal.  The card in your arsenal must have the same suit as the card you're attacking.  Your arsenal card must also have a higher rank.  Once a card is captured, remove it from the map and place it on top of the arsenal card that captured it.  The captured card is now your arsenal card.

An arsenal card of your suit can be used against any suit.  Although, once it has performed its first capture, it's permanently fixed at that new suit (since the captured card is now your arsenal card).

For example, in the position above I used the eight of diamonds to capture the six of clubs. That gives this position:

The vacant space in the map is now part of my territory.

Conquer


The final move available during a turn is to conquer an opposing king.  To conquer an opposing king, he must be face up and at least 51% of his adjacent spaces must belong to your territory.  For example, if a king has eight adjacent spaces, at least five of them must belong to your territory.

Once you've conquered an opposing king, remove him from the map and place him near your arsenal.  All face up cards of his suit are now part of your territory too.

Tech Tree Variant


Many 4X games have a technology tree. Learning a technology grants the player a new ability.  A tech tree can be added to 4X Solitaire with a slight adjustment to the rules above.

After dealing your arsenal, but before shuffling kings into the deck, choose one arsenal card to be your technology.  The technologies are determined by the suit of the card you choose:

  • spades - flip over one card anywhere on the map
  • hearts - conquer with only 50% of a king surrounded
  • diamonds - explore an entire row/column instead of adjacent cards
  • clubs - capture any enemy card, except a king
Set your technology card aside and deal another arsenal card in its place.

If you choose to play your technology card during the game, you can play it only once and using it counts as a turn.