Hardscrabble 🍫

By Max Jacobson

Fun method names in Ruby

08 Jun 2016

One thing I like about Ruby is that you can use a little punctuation in your method names, which can help you write expressions that read like nice sentences:

delete_user user unless user.special?

Kind of fun.

I knew a guy who liked to use these question mark methods in conjunction with the ternary operator to write code that reads like a panicked friend:

user.special?? protect(user) : delete(user)

The double question mark always makes me smile, which makes me wonder… Can I just define a method with double question marks right in the method signature? Like this:

class User
  def special??
    name == 'Max'

Turns out: nope. That’s a syntax error. Not valid Ruby code.

Well… OK. But this is Ruby, so there’s not just one way to do a thing. There’s another way to define a method… Let’s try this:

class User
  def initialize(name)
    @name = name

  define_method("special??") do
    @name == 'Max'

                name??") do
    puts "sure, why not?"

  define_method("!?") do

user = User.new("Max")
user.public_send("special??") #=> true
user.public_send("!?") #=> "‼"
user.public_methods(false) #=> [:"special??", :"multi\n                line\n                method\n                name??", :"!?"]

Haha that works!

OK it’s not as satisfying calling the methods with public_send, but as far as I know, it’s the only syntactically-correct way to call these methods.

Articulating my Vegetarianism

05 Apr 2016

note: this is going to be sort of personal and self-indulgent and I’m mostly writing it for myself to work out some ideas and make some decisions

I’m writing this from vacation, in Mumbai. Last year, I googled “best vegetarian cities” and Mumbai was near the top. New York City, where I live, was also near the top. It’s not a shock – New York has many specialty restaurants that focus on vegetarians and vegans, and almost any restaurant has something for me. But after spending a few days in Mumbai, I think it’s truer here.

In software, we sometimes talk about “sensible defaults”. If you’re going to provide options to your user to change the behavior of your app, the default behavior should probably make sense for the majority of users. I don’t think the majority of Mumbaikers are vegetarian, actually, but the nomenclature suggests it. It manifests like this:

  • FourSquare tips like “best place for non-veg in the city”.
  • Restaurant servers asking “veg or non-veg?”
  • Restaurant signs indicating that a place is “pure veg” (which I think means it’s suited for Jain vegetarians)

I like that the “non” is attached to “veg” and not “meat”.

If you become a vegetarian, people will want to know why. I’ve been a vegetarian for a little over three years, and I often struggle to come up with a good answer. This dissatisfies people, myself included.

The truthful answer is that I’m a vegetarian today because I was a vegetarian yesterday and for no other conscious reason. This of course raises a few questions:

  1. why did I start eating vegetarian?
  2. what do I like about eating vegetarian?
  3. what do I do next?

1. Why did I start eating vegetarian?

In February 2013 my toe hurt. I thought maybe it was broken. I had a vague memory of stubbing it badly while walking in the snow. There were drinks involved.

The doctor x-rayed me and said it looked fine. No broken toe or anything.

“You probably have gout” (I paraphrase).

Gout, as I understood it, is a form of arthritis. If your diet is too purine-rich, uric acid causes crystallization in your joints, which can be painful or uncomfortable. (This is probably not a fully accurate definition of gout – I’m writing without WiFi currently and going from memory from a conversation 3 years ago) He took some blood to assess the levels of uric acid and gave me a cheat sheet of foods to avoid.

He didn’t tell me to become vegetarian. He told me to moderate my levels of purine by limiting my consumption of specific foods to lower levels. The list was kind of surprising to me: I recall spinach and oatmeal being on the no-fly list. There were specific amounts of red meat I was recommended to eat in a week, limited to a few ounces. Similarly for other meat, maybe a little more generous.

I’ve never been a very conscientious eater. I still don’t feel like I understand the basics of nutrition. I wasn’t excited to memorize a list of foods to eat or to buy a kitchen scale. I decided to try eating vegetarian for a few weeks and see if the toe pain went away.

It did.

Curiously, the blood test showed normal levels of uric acid. I might’ve had it, anyway although I may never know.

I think in the first few weeks I was just superstitious and didn’t want the toe pain to return. It was very inconvenient! I could barely walk.

And then it became a habit and I forgot about stopping.

In the interim, I’ve bought a few books about veg* eating, but I think I’ve only finished one: Eat & Run. It’s a very inspiring memoir about a vegan ultra-marathoner. This dude runs 100+ miles at a time powered by smoothies, salads, and black bean burritos. He makes a very persuasive case for veganism as an ideal diet for some kinds of athletic pursuits. I’m not an athlete, but I do encounter people who insist that they “could never be vegetarian” because their gym regimen requires amounts of protein which would be impossible, inconvenient, impractical, or unaffordable to attain through a plant-based diet. They’re probably right, I don’t know their life. One takeaway from the book I took away is that most Americans are consuming too much protein. I like to share that when people worry about my protein.

People worry about my protein all the time. “But how do you get your protein?” People need to know. I’ll tell ya: I don’t worry about it. I’m still not a very conscientious eater, and I feel pretty much fine. I think I feel a little better than before, but I don’t really remember.

(This post continues not to be medical advice.)

2. What do I like about eating vegetarian?

There are a few benefits I’ve picked up on, which I’ll enumerate now, as they occur to me.

Easier decision making

Some people talk about clothing this way: I wear the same thing every day so I have one fewer decision to make each day. I haven’t heard people talk about food in the same way, but I think it’s similar. I have the personality where I feel compelled to read the whole menu before I make a decision, lest I make the mistake of overlooking something I might like. Have you ever been to a diner? These menus are an astonishment. I can get thru a menu much quicker when I can skip all of the non-veg items. No more “please, come to me last”; I know what I’m ordering.

No more storing and cooking meat

I used to try to cook meat. I was real bad at it. I couldn’t make a burger without setting off the smoke alarm or undercooking it. I couldn’t defrost a chicken breast without accidentally cooking it a bit, which I found kind of gross at the time but pushed down. I didn’t really enjoy handling raw meat – it’s kind of slimy and sticky, right? I don’t really remember, and maybe it’s grown more ghoulish with distance.

No more gristle, no more veins, no more bones

It’s been a long time since I’ve taken a bite and felt a surprising popping resistance in my mouth. I used to secret unpleasant, gristly bites into napkins. I used to worry I wasn’t effective at extracting as much meat as I could from a bone. I used to avoid eating veins. No more!

Physical comfort

Meat sits like a lump in your stomach in a way that vegetables don’t. Restaurants sometimes serve these giant sandwiches, burgers, steaks… And I would eat the whole thing, and it would just sit there. Look, I don’t want to go into too much detail about gastro-intestinal scenarios. But let’s just say it’s harder to cause problems when you skip all that stuff.

Moral correctness

This is a touchy one. When a meat eater asks me why I’m vegetarian, what they really seem to mean is: do you think I’m an asshole? I don’t think you’re an asshole. But I do think it’s morally correct to avoid eating meat.

I don’t think it’s majorly evil. But I think it’s kind of wrong.

I don’t feel strongly enough to try and convince others to give up meat. But I do take a small amount of pleasure in feeling like I’m doing the right thing, the same feeling I get when I recycle. That’s the moral level I put it at. It’s a nice thing to do.

I ate meat for 24 years and didn’t eat meat for 3 years. I think of it like I’m offsetting some damage, paying off some debt. If I take that thought to its conclusion, I should remain vegetarian for another 21 years, after which point I would be in the black and could start eating meat again guilt free.

That’s not necessarily the plan, by the way.

Having a label for my diet

There are many diets. I’ll list a few (summarized crudely):

  1. Omnivore – I’ll eat anything
  2. Kosher/Halal – I’ll eat anything except a few specific things
  3. Vegetarian – I’ll eat anything except an animal
  4. Pescaterian – Vegetarian, except I’ll eat seafood
  5. [?????] – I’ll eat anything except red meat
  6. Vegan – I’ll eat anything unless an animal was involved
  7. Jain vegetarianism – I’ll eat anything except animals, eggs, and vegetables which grow in the ground

Before I stopped eating meat I didn’t belong in any of these categories and I was kind of embarrassed about it. Not a deep burning shame or anything, but I had a hard time explaining it, and I was put into some uncomfortable situations. My diet was something like: “Inverse Pescatarian – I’ll eat anything except seafood… or mushrooms… or green olives… or solid tomatoes… or a few other things”. Not great! I’m very proud and happy that I fit into a group now, called vegetarian. People understand it and people have been mostly happy to accommodate what they can understand.

And, happily, I’ve expanded to fill the space I entered and have come to appreciate many or most of the vegetables I used to discriminate against.

If I were to start eating meat again, I think I would need to eat seafood as well, or I wouldn’t belong to a group anymore.

3. What do I do next?

I’m writing this out because recently I’ve been tempted to eat meat again and I wanted to explore the idea.

Here are my temptations, as they occur to me:

  • Shake Shack burger
  • McDonald’s burger
  • Wendy’s burger
  • Most other burgers
  • sliced pastrami – specifically in a pastrami reuben from a specific deli in Vermont near where I lived senior year of college
  • boneless spare ribs at literally any takeout Chinese restaurant
  • pork belly bao at Baohaus
  • Chicken Parmesan at an Italian restaurant near where I grew up
  • Lamb … in some context? I forget when I ate lamb. Maybe it was goat? Something kind of tough and rich.

My mouth is watering as I think about these. But it passes pretty quickly.

I fear if I started eating meat again, even slowly and carefully, I would shortly be subsumed by it.

And I really have no desire to start eating seafood.

And no real reason.

Well, it ain’t broke.

how to run shell commands from ruby if you care about their output or if they failed

31 Jan 2016

Recently I made a new gem called shell whisperer which you might find useful for when your ruby programs need to run shell commands.

Let’s say you want to write a script which prints a summary of the current directory. The desired output is:

There are 213 files in this git repo.
Last commit: fixed a typo

There are two questions we need to ask the shell in order to print this output.

First question: how many files are there in this git repo?

First answer: we can ask git to list the files in the repo, and pipe the list to the word counting command to get the answer:

git ls-files | wc -l

Second question: what is the last commit?

Second answer: we can ask git for the log, limited to the most recent commit, and formatted to include just the first line:

git log -1 --pretty="%s"

So far so good, but how do we run these commands from Ruby?

The language provides two ways that I’m aware of:

# backtick style
`git ls-files | wc -l`


# system style
system 'git ls-files | wc -l'

What is the difference? I don’t want to go into all of the nuances (see this SO post for that and more) but I’ll share how I think of the difference:

  1. if you use the backtick (`) style, the return value is whatever was output by the command – but only STDOUT, not STDERR, so you’ll miss error messages
  2. if you use the system style, the output from the command will go to STDOUT, as if you had run puts and output some text, and the return value will signify whether the command failed or not

So our program might look something like this:

count = `git ls-files`.each_line.count
message = `git log -1 --pretty="%s"`.chomp
puts "There are #{count} files in this git repo."
puts "Last commit: #{message}"

And this is okay.

The issue becomes: well, what do you if you care that the command might fail? The system style allowed for checking the return value to see whether it succeeded or failed, but there’s a reason we’re not using the system style: we care about capturing the output of the command. So with the backtick style, we can capture the output, but (seemingly) we can’t capture the successfulness.

Well, we can, it’s just a little awkward:

count = `git ls-files`.each_line.count
raise 'list failed somehow' unless $?.success?
message = `git log -1 --pretty="%s"`.chomp
raise 'message failed somehow' unless $?.success?
puts "There are #{count} files in this git repo."
puts "Last commit: #{message}"

Which, OK, kind of cool, but what if we want to know why it failed?

This is possible:

count_or_failure_reason = `git ls-files 2>&1`.each_line.count
raise count_or_failure_reason unless $?.success?
message_or_failure_reason = `git log -1 --pretty="%s" 2>&1`.chomp
raise message_or_failure_reason unless $?.success?
puts "There are #{count_or_failure_reason} files in this git repo."
puts "Last commit: #{message_or_failure_reason}"

Let me attempt to explain this. The 2>&1 part means that we want the STDERR stream to be directed to the STDOUT stream, so that we’ll capture either one (or both). This gives us access to the reason the command failed, if it failed, but still gives us access to the output if it succeeds.

I found myself doing this in multiple places, so I decided to wrap this pattern up in a tiny gem, which allows you to instead write your program like this:

require 'shell_whisperer'
count = ShellWhisperer.run('git ls-files').each_line.count
message = ShellWhisperer.run('git log -1 --pretty="%s"').chomp
puts "There are #{count} files in this git repo."
puts "Last commit: #{message}"

If any of the commands fail, that error message will be re-raised as a ShellWhisperer::CommandFailed exception, so you can handle that as you please.

The node.js community seems to be all about tiny modules, and I think that idea is very cool, and I’m hoping to find more opportunities to do that with Ruby.