L

Lane Sawyer🌹

Humanist, vegan, minimalist, programmer, collector of labels.

The Why and How of Rust Declarative Macros

In order to prepare to conduct a technical interview of a potential future co-worker, I decided to try to solve the problem we would be presenting to the candidate. I chose to do it in Rust (even though we don't use Rust on my team) so that I could approach the problem with a fresh perspective and potentially learn some new things about my favorite programming language.

It turns out revisiting an old problem using a dramatically different programming language will teach you a lot! I wrote four different solutions using different approaches and patterns, which helped me better understand Rust's standard library and how to write more "Rusty" code. In addition it prepared me to better understand what the interviewee might do in the interview so I can ask good questions to see how they think.

But the biggest thing I learned through this exercise was how to write Rust declarative macros, which this post is all about.

Why Use Declarative Macros

I've never worked with a language that uses macros before and reading about them has always scared me a little. Code that writes other code, but with special syntax? Yikes. Since meta-programming can become extremely complicated, I've never reached for it to solve any problems, but I stumbled across a good opportunity to dive into it when writing tests for my interview answers!

While testing my potential solutions, I found myself repeating the same exact lines of code over and over, with minor variations:

// Tweak the test array to check the different conditions in each test
let test_array = vec![3, 3, 4, 2, 4, 2, 4, 4];

let first_result = find_answer_1(&test_array);
let second_result = find_answer_2(&test_array);
let third_result = find_answer_3(&test_array);
let forth_result = find_answer_4(&test_array);
// Add another line here in every test when a new function is made

assert_eq!(4, *first_result.unwrap());
assert_eq!(4, *second_result.unwrap());
assert_eq!(4, *third_result.unwrap());
assert_eq!(4, *forth_result.unwrap());
// Add another line here in every test when a new function is made

In addition, whenever I added another solution to the problem I had to update multiple lines in every test case. It was becoming a real headache, and it only got worse with every new problem solution function I wrote.

Thankfully, declarative macros are the perfect tool for writing repetitive code with minor variations!

Now instead of writing all those lines for each test, I only needed to do the following to test each case:

test_find_answer_functions!(
    // The answer based on the list below
    4,
    // The test's input data
    &[3, 3, 4, 2, 4, 4, 2, 4, 4],
    // The names of the functions I want to test
    find_answer_1,
    find_answer_2,
    find_answer_3,
    find_answer_4
    // Add another function name here whenever it's created
);

Isn't that dramatically better? It's extendable too, so when I get an itch to write another solution to the problem in the future, I can quickly tack it onto the end of the macro's arguments and it will also get tested.

How to Write Declarative Macros

So now that we've seen how a declarative macro can simplify writing code, let's dig into how to write them. The following code block is the final macro I came up with, along with a copious number of comments describing the syntax, since there are some different symbols used compared to writing regular Rust that you may not be familiar with:

// macro_rules! is the macro used to create declarative macros
//   test_find_answer_functions is the name of this macro
macro_rules! test_find_answer_functions {
    // Match macro usage where None is the expected output
    //   (matches the literal None, is not macro syntax)
    // - $test_array:expr - array of values to search for the answer
    //   (expr means any expression, e.g. vec![1, 2, 3])
    // - $function:ident - name of the function to test against
    //   (ident means an identifier, i.e. the function's name)
    // - $(__),+ - repeat 1 or more times
    (None, $test_array:expr, $($function:ident),+) => {
        // syntax for repeating based on the number of functions provided
        $(
            // Call function with test data, assert the result is None
            assert_eq!(None, $function($test_array));
        )*
    };
    // Match macro usage where generic type T is the expected output
    // - $answer:expr - value of T we expect to be the answer
    // - $test_array:expr - same array as the None branch
    // - $function:ident - same list of functions as the None branch
    //
    ($answer:expr, $test_array:expr, $($function:ident),+) => {
        // syntax for repeating based on the number of functions provided
        $(
            // Call function with test data and assert the result is the answer
            assert_eq!($answer, *$function($test_array).unwrap());
        )*
    };
}

Like I said before, macros are a bit weird. It's got a whole "who programs the programs" vibe to it that requires you to think about your code's structure differently, so I definitely ran into some issues when making the macro that wrote my tests for me.

If you ever want to try writing your own Rust declarative macros, you'll find a few of the roadblocks I faced written out below so you can avoid them yourself:

Issue 1

The first issue I ran into is that I didn't have a clear idea of what an :expr or an :ident was, so I was getting some weird errors. After reading through the metavariables section of the Rust Reference (which is a deep dive into the inner workings of Rust), I found my problem. I was treating my function name as an expr instead of an ident. Turns out expr is any valid Rust expression, like the value I wanted to test and the list of values to test against, and ident is any identifier, like the names I gave my functions. Little facepalm moment there, but solved easily enough.

Issue 2

The second issue was dealing with the two different patterns of test code. Some of my tests expected a result to be found, while some expected no solution to the test data provided. This led to two different assertions:

// For data with an answer
let test_array = vec![3, 3, 4, 2, 4, 2, 4, 4];
let first_result = find_answer_1(&test_array);
assert_eq!(4, *first_result.unwrap());

// For data without an answer
let test_array = vec![3, 3, 4, 2, 4, 2];
let first_result = find_answer_1(&test_array);
assert_eq!(None, first_result);

That pesky dereference (*) and .unwrap() in the example with an answer is totally different than the second example, where we only have to check the first_result Option to see if it's None!

Thankfully, Rust declarative macros support the same powerful pattern matching that Rust uses. In the macro code above, you'll see two different cases. One for None and the other for Some result.

And that order is important! When writing patterns, you want to start with the most specific at the top so that it's matched against before its more general version. Since None is a macro metavariable of type expr, putting the second pattern first would mean None matched that more generic pattern. I spent a few minutes stuck there until I remembered that particular rule of pattern matching.

Issue 3

Finally, I fought the borrow checker for a bit, since I couldn't easily tell what the final output of my macro would be. Rather than randomly throw * or & into my macro, I decided to finally figure out how to view the compiled code with the following command:

rustc --pretty expanded -Z unstable-options src/lib.rs --test

Now that's a bit more complicated than I would prefer for a debugging command, but it makes sense once it's broken down:

  • rustc is the Rust compiler
  • In order to use the --pretty expanded flag to preserve spacing after compilation, -Z unstable-options is required
  • -Z unstable-options requires the nightly compiler (which can be turned on for a single workspace using rustup override set nightly)
  • src/lib.rs is the name of the file to compile, which is the one I'm writing my code in
  • --test means to compile the test code, which I needed since my macros are only used in the tests

Unfortunately, that final command expands all macros, including the final code for things like assert_eq! and the #[test] attributes on the tests themselves, so it took me a little bit of digging to find my specific macro code. But once I found my macro's output, I could clearly see the borrow checker problem and fix it!

Why Not Use Plain Rust?

I could've written a solution using plain ol' Rust, avoiding macros entirely. The main reason I didn't was I simply forgot that was an option and finished the macro before I remembered that you could pass functions to other functions (which I absolutely love to do!).

I decided to write up a solution using functions. In the end I still feel like macros are a better fit in terms of ergonomics. I had to write two different functions, one for the Some case (when a solution is found) and another for the None case (when there is no solution):

fn test_find_answer_functions_some<T, F>(answer: T, data: &[T], funcs: Vec<F>)
where
    T: Eq + Hash + Debug,
    F: FnOnce(&[T]) -> Option<&T>,
{
    for func in funcs {
        assert_eq!(answer, *func(data).unwrap())
    }
}

fn test_find_answer_functions_none<T, F>(answer: Option<&T>, data: &[T], funcs: Vec<F>)
where
    T: Eq + Hash + Debug,
    F: FnOnce(&[T]) -> Option<&T>,
{
    for func in funcs {
        assert_eq!(answer, func(data));
    }
}

I could've written a single function that handles both scenarios by passing in an option as the answer parameter for the Some case, but that led to me writing this absolutely hideous answer argument as seen below:

test_find_answer_functions(
    Some(&4),
    &[3, 3, 4, 2, 4, 4, 2, 4, 4],
    [
        find_majority_element_two_loop,
        find_majority_element_two_iter,
        find_majority_element_one_iter,
        find_majority_element_counting,
    ]
    .to_vec(),
);

Wrapping the answer in a Some instead of a naked 4 like I could do with the macro was just too much for my perfectionist brain to handle.

In order to match the prettier user-friendly macro syntax, two functions were required. Even then, I had an ugly .to_vec() that I couldn't get rid of (although I'm sure there's a way to do so if I spent a little more time on it):

test_find_answer_functions_some(
    4,
    &[3, 3, 4, 2, 4, 4, 2, 4, 4],
    [
        find_majority_element_two_loop,
        find_majority_element_two_iter,
        find_majority_element_one_iter,
        find_majority_element_counting,
    ]
    .to_vec(),
);

In addition to the less than ideal user interface, the function approach requires a bit more of a heavy lift on the runtime side of things. A macro literally prints out code, and that resulting code can be optimized by the compiler. The functional approach happens dynamically at runtime, so there's a bit of a performance cost there. This toy example isn't concerned with performance, but it is something to consider when making a decision between the two approaches.

Wrapping Up

By this point you should have a high-level understanding of what Rust declarative macros are, where they might be helpful, and some potential issues you might face when writing your own.

While my example was a little contrived, it was a real-world usage of macros that made my life as a programmer a little bit easier and got me excited to look for more substantial opportunities to use macros in the future.

Further details regarding declarative and other macros can be found in the official Rust book, which is one of the best resources out there for learning the language and should be on the reading list of anyone wanting to become proficient in Rust. If you found this article interesting, I think you'd really enjoy the book. It's one of the best examples of approachable technical writing I've ever come across.


If you have questions or comments, feel free to reach out to me through any of the methods on my About Me page, or leave a comment in my guestbook!

COVID Summer

I thought this was supposed to be over. The vaccine would show up, everybody would take it, and life would get back to that "new normal" everyone was talking about.

But instead, we're seeing a fourth spike thanks to a brutal combo of the delta variant, vaccine hesitance, anti-vax propaganda, and a general unwillingness to make personal decisions while keeping the general public's health in mind.

Thankfully this hasn't been the worst summer. Last year easily takes the title for worst year ever. I've been able to see friends, regularly go to the climbing gym, and not constantly think about COVID. That was a sorely needed reprieve from the pandemic lock-down restrictions, but now we're sliding back into lock-down mode because this pandemic just isn't over yet.

I don't want to place too much blame on anti-vaxxers. While that group contains a lot of misguided people, there are a select few fraudsters at the root of it all looking to make a buck that should take the real blame. These leaders and their credulous followers are responsible for rising rates of all sorts of preventable infectious diseases, but I think we'd probably still be in the same spot if they didn't exist. The delta variant is brutal. It didn't originate in the US, so a fully vaccinated population wouldn't have stopped it from mutating. Sure, we'd not be facing shortages of ICU and hospital beds had more people gotten the vaccine, but we would likely be facing the similar restrictions that are being put back in place right now to prevent community spread.

Despite all my complaining, I'm pretty lucky. I'm in Washington, where the populace generally values scientific evidence and don't have a governor who is actively working to kill people (like the ones in Florida or Texas). The restrictions here amount to "wear a mask in public" and "please get the vaccine if you haven't yet". Seventy percent of my county is vaccinated, and while we have substantial community transmission right now, it's nowhere near other parts of the US or the world in general.

But I'm scared for the winter. If we get another spike like last year it's going to be the worst one yet. Delta is nasty, and unless something changes we will very likely have to go back to general lock-downs in order to save lives.

Lock-downs suck, as necessary as they may be. My mental health still hasn't rebounded from the trauma inflicted by the isolation and uncertainty of 2020.

Here's hoping the vaccine holds up over the long term so that me and my vaccinated friends and family can try to live some semblance of a normal life, but I'm mentally preparing for the worst.

The Future of the Web: Why It Doesn't Have to Be JavaScript

I am a professional web developer. I use JavaScript on a daily basis, but to be honest I harbor a bit of hate for the language. Don't get me wrong, it does its job and does it well enough, but... there's a reason TypeScript exists.

Despite its glaring flaws, JavaScript is currently the most widely used programming language in the world. JavaScript's stratospheric growth is largely driven by the growth of the Internet and web technologies. And while JavaScript exists on the server, it was born for the web. For decades it's been the primary way to write websites and that won't be dramatically changing anytime soon.

However, the future is on the horizon. WebAssembly (WASM) is a technology being developed as a new type of bytecode meant to run in web browsers. While WASM is relatively rare to see in the wider programming world right now, it has been supported in modern browsers for years.

Do you know what this means?

We're free.

Free from being forced to use JavaScript, a language thrown together in 8 days with some of the most confounding behaviors I've ever encountered in my years of programming.

So what do we do with all that freedom?

Work with a better language!

WASM is likely supported by your favorite language, and frameworks and tools for building web apps are being created and refined every single day. So the next time you need to build a website, give your technology selection a second thought.

It doesn't have to be JavaScript.

WASM + Rust

My favorite WASM-supported language is Rust (which you already know if you've ever had a conversation about programming with me). During the pandemic while I had nothing better to do with my free time, I read The Rust Book and fell in love with its thoughtful design and developer experience. I enjoy it so much that it's my goal to someday work with Rust professionally.

However, the web development ecosystem still needs a little more growth so it will be a bit longer before I get paid to write a web app in Rust. Other languages face the same barrier, but exciting projects like Yew (Rust) and Blazor (C#) are getting better each day.

Dicebag

Recently I decided to put WASM to the test with a serious effort to build a website completely in Rust, doing my best to select tooling and frameworks that replicate what I do with JavaScript/TypeScript during my day job.

The result is Dicebag! I regularly play Dungeons & Dragons and haven't been happy with the online tools my group and I have used, so I'm building tools that will help us have a better experience. As of this writing, it's an ugly, non-interactive Character Sheet, but it gets a tad bit better every time I work on it. If you're curious at checking out the code hop on over to the repository on GitHub. Contributions are more than welcome!

Despite the site not being very fancy, I am very happy with the progress so far regarding the tooling to facilitate development. Here's a short list of each framework or tool I'm using with its equivalent in JavaScript land (where applicable):

  • Trunk replaces Webpack
  • Yew replaces React
  • Rust-specific GitHub CI/CD actions

So far I've really enjoyed the experience with the tooling. None of them have reached version 1.0 at this point, but things are functional and you can produce a complete app with them. I'm sure I'll run into more issues as the site becomes more complex, but the basics are there!

My goal with Dicebag is to provide tools like character sheets, equipment and spell management, custom views to facilitate gameplay by presenting contextually relevant choices, a DM encounter builder, a dice roller, and more. It should be perfectly usable whether you're the only one using it in your group or if everybody is.

In addition, making this site a success will prove out the technology and give me a story to tell the next time I try to convince my co-workers to choose Rust on their next project. Plus, finding the pain-points allows me to contribute to the ecosystem's development by opening issues on GitHub or even contribute code to make the tools better.

We'll see where this project goes, but I'm excited!

Someday I'll never have to write JavaScript again.

Vaccinated!

I got my second poke yesterday!

A few hours after getting my second dose of the COVID-19 vaccine, I was very tired and took a five hour nap, waking up just in time to go to bed. Unfortunately, I woke up in the middle of the night soaked in sweat with a pounding headache and a variety of bad dreams marching through my brain.

It was an awful night, but I eventually got back to sleep and woke up at 10 A.M. feeling great. The next day was filled with dog park adventures, cooking delicious food, reading books, and playing video games.

Totally worth it.

Trading a night of weird dreams and restless sleep for catching COVID-19 is an excellent trade.

If you haven't gotten your vaccine yet, please do! It will protect you and others from an awful and potentially fatal sickness. The people in my life who caught COVID-19 had an awful time for weeks dealing with its effects.

Vaccines are safe and effective. I consider it a part of my civic duty and am proud to have done my part.

Let's play board games at my place soon, y'all!

First Dose of COVID-19 Vaccine!

I got my first poke last weekend. Next one is on May 8th!

My life is about to become very different, very soon. I can't wait!

Go get your vaccine folks! It's a game changer. Life won't be back to "normal" (or whatever new normal we end up with) for quite a while, but being able to hang out with friends indoors playing board games or D&D will be an incredibly welcome change.

A Year of Pandemic Life

It's been a whole year. One that feels like a lifetime.

A year ago I left my office at work for the very last time. I expected to be back in a couple months, but those months dragged on. I got a pay cut, which spurred me to find a new job. And even if I hadn't changed jobs, I still would not have revisited my old desk to this day.

Worldwide tragedies have a way of shaking things up, and I'm sure others have felt the whiplash of well-laid plans being abandoned and replaced with activities that were incomprehensible a year ago.

I had no plans on leaving the company I worked at for 6 years last March. I had no plans on my pay being dramatically cut. I had no plans to go live with my parents to save some money. I had no plans to build a home office. I had no plans on adopting four plants. I had no plans on reading over 50 books in a single year. I had no plans to learn how to live in solitude.

But a year of a pandemic burning through the world will do strange things to plans.

Thankfully, humans are incredibly adaptable. Our current quarantine setup here in Seattle now gives me the same feelings of normality that I had a year ago. Our hedonistic treadmills largely keep us sane even when the world has gone to hell.

There's a light at the end of this year of darkness. Vaccines are being distributed in the US faster than I ever imagined. I fully expect to be vaccinated by the end of May! Then life will start to get back to the "new normal" that we'll have for the next few years. Until the world is vaccinated, we're going to be dealing with COVID restrictions both here and abroad for quite a while, unfortunately.

But getting together with friends and family won't be dangerous anymore. I won't need to allocate my time to see different friends in 2-week increments. I won't have to wear a mask when I sit on my friend's couch while we catch up with each other. I won't have to constantly cross the street while walking my dog to avoid other people on the sidewalk. So many things will change with the vaccine, and those changes are sorely welcome.

Even though we'll be wearing masks for months more and we'll all still have the pandemic on our minds, the small changes that vaccines enable will be more valuable than any international trip. I still desperately want to travel, especially after spending some of my health being on travel projects as a consultant where I built up plenty of airline miles. Those trips will come with time...

The world will be strange for quite a while longer, but drastic changes are coming with the vaccine.

I can't wait to get poked!

Farewell Flash!

Today, Mozilla shipped Firefox 85, in which they completely ripped out Adobe Flash functionality. And while Google hasn't quite shipped their Flash-less Chrome release yet, I don't care because Chrome is essentially Google-branded spyware that has no business being on my machines. So, in my world, Flash is dead. 💥💀⚰️

For those of you who didn't grow up in the early '00s playing online Flash games or watching Flash cartoons, Adobe Flash was an easy-to-use technology for building interactive content that could run in a web browser. This was back when the Internet was just finding its feet and technological standards had not yet been agreed upon. Adobe, makers of Photoshop, was one of many companies that created their own tools that far surpassed the abilities of the early Internet.

The content for websites like Homestar Runner and Newgrounds, among many others, were all built using Flash. But internet browsers didn't understand how to display Flash content, which meant users had to download an Adobe Flash plugin.

Once the browser had the plugin installed, Flash sites "just worked". You'd occasionally get pop ups on your computer to update the Flash plugin occasionally, but that was a small price to pay to watch Trogdor burninate the countryside!

Unfortunately, downloading all those plugins and updates gave malicious actors plenty of opportunities to write viruses and take control of another person's computer. Many folks dismissed those pesky update notifications, and millions of computers were left vulnerable because they had outdated versions of Flash. It was a security hole that was frankly not worth having just to watch a couple cartoons or have fancy interactive websites.

Thankfully, the IT community worked together to create web standards that enabled the same sort of functionality that Flash provided, but using a single approach that everyone agreed to follow. If you've seen technology acronyms like HTML5, it's that kind of stuff that helped killed Flash. After we built the modern Internet, Flash really didn't have much of a purpose. And In 2017 Adobe announced Flash would die at the end of 2020.

Spoiler alert: we made it through 2020!

I like to think Flash sacrificed itself to appease whatever apocalyptic gods were lurking among us last year and they apparently deemed it an acceptable enough offering that we get at least one more year. 🤞🏻

But as wonderful and amazing as Flash was in its prime, technology marches onward.

That said...

Flash has been reborn using a really cool piece of technology called Ruffle so that we can continue to enjoy Teen Girl Squad cartoons until the heat death of the universe.

And yes, it's written in Rust! 🦀

But the important thing is that nobody will be writing new Flash programs, outside of hobbyists or any companies without the forsight to switch to modern technology.

Fareware Flash. The cartoons and websites created by you were an incredible part of Internet history.

You will not be forgotten!

Relief

Joe Biden is officially the 46th President of the United States!

The inauguration was vastly different than any we've seen before. The new administration did the smart thing and limited attendance, both because of the pandemic and the threat of violence from those who participated in the January 6th violent insurrection/most incompetent coup attempt ever.

I was fully expecting something to happen, but was immensely relieved when President Biden walked back up those stairs into the relative safety of the Capitol building.

Today is a good day. The weight of four years of stress from what will likely go down as one of the worst presidential terms in history has evaporated. A burden lifted from my shoulders.

No longer will I be upset at my president for enacting harmful, racist, neo-liberal, classist policies.

Now I will be upset at my president for enacting slightly-less-harmful neo-liberal, classist policies! What a wonderful change lol

But seriously. I think Biden has the potential to become one of the most transformational presidents in modern history. He wants to address the pandemic. He wants to start a clean energy transformation of our economy. And he wants to unite instead of divide.

That's a very good start, and while Biden was far from my first choice of presidential nominee I'm actually looking forward to the next four years.

Let's do this.

My 2021 Government Action Wishlist

After the unlikely, but very welcome, results of the Georgia special elections, new opportunities abound. It's been ages since we've had a unified Democratic government that will now have the ability to get things done!

This is my wishlist of everything I want to see happen before 2022, when the GOP gets its next shot at taking back power. So many of these things are pie-in-the-sky given the type of people currently in power, but I am optimistic that some will happen or we'll at least make progress towards others.

Now, let's check out everything I want to see happen to make the United States the incredible nation we have the potential to become:

Environment

  • Remove all gas and oil subsidies
  • Use the gas and oil subsidies to supercharge green energy initiatives
  • Create a federal job guarantee with unionized jobs building green energy infrastructure
  • Make fracking illegal
  • Stop any future oil extraction sites from being built anywhere in the United States
  • Dismantle pipelines across the nation

Travel

  • Build high-speed rail connecting every major population center
  • Nationalize at least one airline and use it to experiment with making air travel greener
  • Subsidize public transportation with incentives for cities to build out multi-modal transit networks
  • Subsidize electric vehicle purchases
  • Strengthen unions so workers who can work from home have the power to do so

Drugs

  • Remove cannabis as a Schedule One drug and immediately release all people in prison with cannabis-related charges
  • Fully legalize cannabis and tax it
  • Pump those cannabis taxes into our education or health system
  • Decriminalize all drug use and possession
  • Create safe injection sites with treatment programs to help people get out of their addictions

Taxes

  • Impose a progressive tax rate on all forms of income, with the upper bounds in the 90% range for the obscenely rich
  • Bring back a strong inheritance tax
  • Implement a carbon tax

Education

  • Make public universities tuition-free
  • Forgive all federal student debt
  • Pay collegiate athletes and separate the financial destinies of universities from sports
  • Create more trade schools and stop encouraging everyone to attend a traditional university

Healthcare

  • Create a single payer system
  • Write laws that require the portion that employers used to pay to insurers to be given to the employee as wages (to be taxed) so that companies don't just pocket that money
  • Built out a redundant hospital system so the shock of future pandemics and other nation-threatening health issues can more easily be handled

Food and Water

  • Prohibit factory farming
  • Ban mono-culture farming practices and start using restorative and sustainable farming techniques
  • Ban private companies from selling bottled water and profiting off of public water supplies
  • Build out public water sources, including fixing the water systems of Flint and other cities

Technology

  • Make the Internet a public utility
  • Break up big tech into separate companies, especially Amazon and Google
  • Provide more funding to government scientific institutes
  • Create strong privacy rights laws for Internet users
  • Build out a federal Government as a Service (GaaS) platform to create an open source platform of tools for running a state
  • Create a public cloud used to run government technology and provide it as a service to citizens, complete with open source, privacy respecting tools

Voting

  • Switch to a ranked choice voting system
  • Abolish the Electoral College so the presidency would always reflect the will of the American people
  • Expand the House of Representatives to reflect the growth of the nation since we froze the number in place
  • Put an end to American imperialism by adding Puerto Rico, American Samoa, Guam, U.S. Virgin Islands, and Northern Mariana Islands as states or give them independence

Trade

  • Negotiate trade deals that require a basic level of human rights and worker protections with our trading partners
  • Provide tax breaks to corporations that stay within the United States, or add a tax for being a multi-national corporation
  • Open up borders so that people can move just as easily as goods

Economy

  • Take possession of empty or infrequently-used housing and give it to the homeless
  • Add a tax to any remaining housing being used as an investment vehicle instead of a domicile
  • Strengthen union power and create unions for new sectors of the economy, especially in the technology industry
  • Create a substantial tax on multi-national companies stashing their money in tax havens
  • Provide a universal basic income (using the taxes on the ultra-wealthy)
  • Do major trust busting on Big Tech, media conglomerates, Internet service providers, and the many other industries that have consolidated over the last few decades

Now, I'm sure I've missed many other things that I would love to see happen, but this is what came to mind in an evening of writing. As you can see, I don't really fit in either political party, but utopian ideation is needed in order to create a new world. Everything in politics must first be birthed as an idea before it can be enacted physically, so this is my little contribution to The Discourse.

If you agree with a lot of this stuff, say hi! If you don't agree, say hi too and let me know why something won't work, because many of these ideas need polishing in order to actually happen. And maybe go write your own list! It's a good way to start building a political platform if you ever decide to run for office!

Democracy Survives

Wow, what a day.

On January 6th, insurrectionists stormed the US Capitol building as Congress was certifying the results of the 2020 presidential election. This came after Trump encouraged his fanatics to march to the Capitol in an attempt to overthrow democracy.

The last time the Capitol was invaded was during the War of 1812, but this is the first time that traitorous flags were flown inside. They brought in Confederate and Trump flags, and I even saw a Mormon waving "The Title of Liberty" (a nationalistic rallying call created by a military general named Moroni, a character from the Book of Mormon).

These domestic terrorists stole government property, invaded the individual offices of Senators and House members, caused Congress to go into hiding in fear of their safety, and embarrassed us as a nation in front of the entire world.

And despite all this, the police response to a literal coup d'état stands in stark contrast to the BLM marches earlier this year. It's a damning indictment of the racism built into our system of policing. There are even photos of officers taking selfies with the terrorists. Only 15 or so people were even arrested today in DC.

But if you march peacefully demanding equal treatment under the law, you get a massive show of force, complete with police brutality.

Over 100 Republican members of Congress supported Trump's call to question the results of an election based on absolutely no evidence of fraud. The Grand Old Party has completed its transformation into the party of Trump, and it must be held accountable for what it's done to our nation. Ted Cruz, Tom Cotton (I still can't get over how his name would be considered too on the nose for a fictional racist... Truth really is stranger than fiction), and the other 12 Senators and 121 members of the House who have entertained Trump's failed coup should be expelled from Congress, just as we expelled those who supported the Confederacy back in the day.

I never thought I'd say anything like that, but damn, we live in extraordinary times.

What Trump did today is worthy of impeachment. Articles are already being drawn up.

What Trump did today is worthy of invoking the 25th Amendment. Discussions are already being had in the Cabinet.

And yet, I have little hope that either of those appropriate reactions to what will go down as the slowest, most incompetent coup d'état will happen in the last two weeks of what will surely be known as the worst US Presidency ever.

The next 13 days will be quite interesting. We're not completely out of this until Biden is sworn in as President. Keep your eyes peeled. You're (hopefully) not likely to see such insanity in US politics ever again, but there is still time for Trump to continue his hissy fit and maybe cause even more chaos.

But I think we've seen the worst after today. It looks like our democracy will hold. Congress reconvened and finished certifying the votes.

Joe Biden will be the next President, and while he was far from my first choice, I couldn't be happier that the party that birthed this coup d'état no longer is in power to continue fucking over our nation.

Bye 2020

Phew, we made it. Done with the worst year ever!

I'm decently confident things can't get worse. Trump's loss and the coming rollout of the COVID-19 vaccine will remove two of the most immediate threats we face. I'm hoping the Biden administration hits the ground running and is able to fix a lot of the issues we have now around inequality, climate change, student loans, homelessness, etc.

Yeah... that's a grab bag of wishes, especially if we lose the Senate. But I'm holding onto that hope for now because it makes me feel happy, and sometimes you just gotta do what makes you happy!

It's also been a while since I've posted. All the stress from the election, pandemic, adjusting to a new job, and general laziness has gotten to me, but I'm hoping to write a bit more in 2021, especially around technical topics.

Here's to a much better year than the last!

Vote!

In the United States, the general election is coming up in a couple weeks. While every election seems like "the most important ever", this one is particularly noteworthy. We're in the middle of a global pandemic, climate change is creeping closer, and economic inequality abounds.

American democracy is under attack. Voter participation has been incredibly low over the last couple decades, and blatant voter suppression tactics are deployed regularly, like limiting the number of ballot drop boxes or polling places to make it difficult to cast a ballot.

Despite our historic lack of participation, early voting levels are drastically outpacing past elections!

While our country faces a deep political divide, I do think we can all celebrate the fact that more citizens in this election are exercising their democratic right to vote. High levels of voter participation theoretically leads to representatives being elected who more closely mirror the desires of the populace. And it's my hope that high turnout will lead to many broadly popular policies (weed decriminalization, infrastructure and healthcare improvements, progressive taxation reform, etc.) finally being enacted by the politicians in D.C.

I know many people are unhappy with the choice for President. But there are far more elections on the ballot than a single office. Even if your favorite presidential choice doesn't win office, you can still have an impact on your local and state races, who are arguably more integral to making things happen that you'll notice in your day-to-day life.

So go get educated. Read voters guides, newspaper and union endorsements, the candidates platform, and any other reliable information you can find. Then cast your vote for the people who are closest to building the world you dream of.

The last four years have been a mess for me. Voting for Joe Biden, despite him being one of my last choices, was an incredible opportunity for me to be the change I wish to see in the world. I've felt a bit powerless following politics over the last few years. Submitting my ballot felt amazing. I did my bit for building a better world.

Please, do your bit too!

If you're new to voting or need a bit of help, Vote.org is a fantastic resource to help you exercise your civic duty and one of the most important democratic rights you have!

Let's smash turnout records. Let's get the will of the people heard and give the next government (regardless of who wins) a clear mandate to enact their agenda and (ideally) make the world a better place.

Back in Seattle!

I'm all settled in my new apartment in the Ballard neighborhood of Seattle. I spent some time this morning walking around the neighborhood and seeing what kind of food, shops, and entertainment are nearby and I found some real gems! The neighborhood is quiet but alive, and it's got basically all the things I need to enjoy living in an area (movie theater, variety of resturaunts, rock climbing gym, good bus routes, and a Trader Joe's)!

I miss being with family in Utah, but I also enjoy the independence that comes from moving to the big city. I wish COVID were over so that life could be a bit more normal, but until then I'll make the most of what coronavirus-era Seattle has to offer.

Next step is getting some rugs and decorations to mute a bit of an echo in my apartment haha. Luckily there are lots of cute shops nearby with that kind of stuff that I can explore and make this place really feel like home. After moving for the third time in less than ayear, I'm ready to stay in one place for a while!

New Job!

I've got some exciting personal news: I recently accepted a position with the Allen Institute for Brain Science! I'll be working as a web developer to build out a scientific data sharing platform.

After six years in IT consulting, I've decided to make the jump to the non-profit sector. I've wanted to work for a non-profit organization for a while, and now is the time for me to make that dream come true.

I started my first job out of college with Pariveda Solutions, and I'm incredibly grateful to have been there for so long. It's a fantastic place to work and I'm glad I landed there to start my technology career. But my life has changed a lot in the six years I was with Pariveda, and it felt like it was time to move on.

So in August, I started my first job hunt in forever.

It was a strange experience. I literally had not looked for a job or touched my resume while I was with Pariveda since I had been very happy working there. So I brushed up my resume, sent it to some friends who gave great feedback, and then started sending out job applications like crazy!

Here are the stats regarding the applications I sent out:

  • 63 applications
  • 35 ghosted
  • 21 nos
  • 4 technical assessments
  • 2 "no positions available" responses
  • 2 post-assessment interviews
  • 1 offer

I applied for a lot of "pie-in-the-sky" jobs, like Discord, Reddit, Nintendo, and other companies whose products and services I enjoy. I also looked for some Rust-specific jobs since I really enjoy that programming language. And I applied for some that were building tools to address climate change.

Eventually I ran across the Allen Institute a couple weeks into my search. I knew about the organization because I walked by their building in Seattle every day for a couple years during my commute. I always thought it would be cool to work for them or another non-profit, but I never really looked into it because I thought it was just a bunch of scientists who didn't have a need for a web/cloud/backend software engineer. Thankfully I discovered that's not the case!

I got through the interview process, met a good portion of the team, and was literally dancing around when I received the offer. I'm super excited to work on web technologies to build out useful graphs, charts, tables, and other tools for exploring the data generated by the scientific teams at the Allen Institute. It's a fantastic opportunity for me and I'm really grateful that I get a chance to use my skills to further what humanity knows about the brain. If I can do anything to help solve issues like brain cancer or Alzheimer's disease, I will be ecstatic.

I'm moving back to Seattle right now to start the new job next week, which means I'll get to see my dog Kaladin again and many of my Seattle friends! I had a really good time living in Utah with my family, but it also feels nice to return to the Pacific Northwest.

I'm starting a new chapter in my life, and it's scary and exciting and new and terrifying. I can't wait to see how it goes!

I'm So Done With This Country

We're a bunch of racists who use police power to punish black people because we never got over losing our slaves.

Fuck the poverty to prison pipeline, the privatization of prisons, and the systemically racist police force and legislation that keeps it all running.

(Context)

Tyranny of the Minority

The United States is democratic republic. That means that the people elect the representatives who make decisions on our behalf.

But the democratic part of our system has been under attack for decades. You can see it clearly with the Supreme Court nominees.

When Trump appoints a third SCOTUS judge, five of the nine serving justices will have been put in place by presidents who lost the popular vote and confirmed by Senators representing a minority of citizens.

That's hardly something you can call democratic.

While George W. Bush appointed both his nominees in his second term, where he won a majority of votes, that was arguably because of the wave of nationalism from the 9/11 attacks and his natural advantage as an incumbent. He should have never been in the position to nominate Supreme Court justices in the first place in a second term that likely would not have occurred had Gore won the presidency.

As for Trump, he lost the popular vote by almost 3 million ballots (a much wider margin than the 500,000 lead Gore had). The Electoral College once again paved the way for a minority president to be in place to appoint multiple SCOTUS judges, including the stolen seat of Merrick Garland.

The Electoral College is an inherently undemocratic institution, and that has benefited Republicans twice in the last 20 years.

As for the Senate, it becomes more unrepresentative each and every year as populations boom in urban areas, while rural states grow more slowly. A vote in Wyoming is over 50 times more effective than a vote in California, since both have only two Senators but California has 24 more million people.

When we look at the numbers for the Senates that approved each of the minority president's SCOTUS picks, the undemocratic nature of it all rears its ugly head.

The 109th US Congress approved two of Bush's selections with 55 Republican Senators, representing an estimated 49.54 percent of the US population in 2005 and 49.79 percent of the US population in 2006 (stats taken from census.gov).

The 115th US Congress approved two of Trump's selections with 52 Republican Senators for the first pick and 51 for the second pick. This represents an estimated 44.74 and 44.12 percent of the US population in 2017 and 2018, respectively (stats taken from census.gov).

The 116th US Congress is on the verge of approving a third Trump selection with 53 Republican Senators. Because the 2020 estimates are not provided, using the 2019 estimate gives 47.86 percent of the US population (stats taken from census.gov).

This means that the third branch of government, which is supposedly set up to be non-partisan, will now be a 6-3 conservative majority that will inhibit progressive policies for decades to come.

Republicans have been playing this long game ever since the Southern Strategy. Their gerrymandering, voter suppression, and relentless focus on the judiciary has laid the groundwork for their minority rule.

Is it any wonder why democratic participation is so low? To gain a majority, liberals and progressives need to win far more than 50 percent of the vote. Our two party system has led to a shrinking of the Overton Window to the point where the choice is between two slightly different flavors of neo-liberalism, leading to even more feelings of hopelessness from the electorate.

We must put a stop to this pattern of minority rule. We need a blue tsunami in November, and the politicians elected need to have the willingness to put democratic rules in place to level the playing field and allow for a true democratic republic to emerge.

Here are a few of the things I'm hoping that a Democratic government will accomplish in 2021:

  1. New federal law requiring bi-partisan/non-partisan groups to draw district lines to combat gerrymandering
  2. Ranked-choice voting to stop negative partisanship
  3. An expansion of the House to match historical representation
  4. Add the US territories and Washington D.C. as states to give millions of Americans Senate representation
  5. Publicly fund elections and reverse the disastrous Citizens United decision that gave corporations and the rich an out-sized political influence
  6. Remove the filibuster to eliminate gridlock in Congress so that citizens can elect politicians based on their actions rather than rhetoric
  7. Eliminate the Electoral College to elect the President based on the popular vote

Those seven steps would drastically re-shape American politics and create a true democratic republic. The will of the people would finally be represented for the first time in the 200+ years of the American Experiment.

We spent so much time and energy to prevent the tyranny of the majority that we left a huge hole that the GOP and their minority views have exploited brilliantly. Their bad-faith gamesmanship has deeply damaged our democracy, and we really only have one election left until they permanently entrench their power.

We all must vote in this upcoming election. Another round of Republican leadership will only further minority rule in this country, since they will once again be in power to continue the gerrymandering and judicial appointments that will keep our country from making progress on the biggest issues of our time. Women's rights, climate change, worker's rights, and more are all in limbo. Without a progressive push-back, our country will continue its decline into a corporate oligarchy, and our standing as a world influencer will crumble to dust.