Writing - John Elam


It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures. - Alan Perlis (SICP Foreword)

There is an eternal debate around Object Oriented software vs Functional software, and there likely will never be a conclusion, however, this is why I choose Functional when possible.

The API problem is defined as this - for every abstraction and service we create with software, all consumers will have to spend time learning the API. If you are familiar with concept of domain-specific language, or DSL, you can start to understand the trouble here. As nice as an API is, it introduces a new pattern to follow. But, most importantly, it introduces a new pattern to learn. I first heard the term DSL when I was learning Clojure and LISP. Both give you a magical ability (Google-"homoiconic") to create new languages extremely rapidly, but when you create a new language, you make a DSL. While powerful, it's something new that outsiders will have to learn when reading or modifying your code.

The modern web developer knows APIs well. Typically, APIs are used to gain massive leverage and scalability, without having to write much code, or maintain a complex service. As anyone who has used powerful APIs knows, its great once its working, but most of your time is spent looking over the documentation (which sucks most of the time). If you are lucky, you might get it on the first try, but more likely, you have to keep searching through docs, blogs, and stack overflow to find the essence of what you are looking for. The trouble and frustration comes when you've assumed this service is going to plug and play and easy to set up, but you've just spent two hours learning a DSL that you don't really care to learn.

We don't want to learn an API specific pattern, shape, or json language, BUT WE OBJECT ORIENTED PROGRAMmers spend years making complex APIs.

Let me explain - objects have an API in OOP, we don't call it an "API", but that's effectively what the object is. We use an object, we get a contract that says you can call get(), set(), toString(), foo(), bar(), etc. Not only do our objects have an API layer to access functions/methods, but they have an API to access data (I cannot deny functional programming has a data API, also but I will explain why it's better). Back to objects.

Let's look at a class in .NET Core: PolicySchemeHandler. The actual class doesn't matter for our purposes, but if you're interested, it does some authentication related stuff. Now, if you haven't already, please open up that link and tell me which method sounds the most useful. You may have gotten sidetracked by the long method names, or the descriptions that don't actually say what the method does, but rather where it inherits from (sweet, more hyperlinks to follow to figure out how to use this class). This is the API that you are going to spend at least a few minutes learning, if a lot more. It takes almost a minute just to read the class declaration (public class PolicySchemeHandler : Microsoft.AspNetCore.Authentication.SignInAuthenticationHandler) That's a mouth full!

What I argue, is that this is one class out of hundreds! that your application might need, each with its own interface full of methods. This should not be. Each class you introduce or create for your project brings with it many, many methods that are specific to THAT class alone. Maybe you made a nice interface that required you to implement the sleep() method for the Human, Dog, and Cat classes. Likely, you just typed very similar methods for each one.

So, how does Functional Programming help? I have been spoiled by Clojure, so my opinion will be somewhat colored by my experience with it. In Clojure, we use maps, seqs, vectors, lists, a few other primitive data structures to do all of what a class previously did for us. Something wonderful about this is that I can make 1 function that will accept all of the aforementioned data structures as a parameter and return the correct answer. No need to implement sleep() 3 times (or 100 times for that nasty app you get paid to work on). You implement it once, and it does the magic. You pass in a map with your own shape to represent a human, dog, or cat, and the function treats them all the same.

Would you rather have 1 sleep function for 100 different animal types, or 100 different animal classes with their own sleep method?

This is not a cherry-picked example, this is the norm. You can gain massive leverage by just treating all data as what it is: data! Instead of treating it like an object that is rigid and forces the burden of implementation detail on YOU.

  • Proficiency in Clojure
  • Proficiency in C#
  • Intermediate Swedish
  • Beginner Russian
  • Option Pricing
  • To Be Continued

In essence, a web framework does one thing - transform text based on a request and some state. So where does complexity arise? Aren't all web frameworks accomplishing the same goal? Let's dream up the world's most simple web page, then build a web framework from there.

You might have guessed it; the world's most simple webpage is literally just text. Notice most tutorials and most frameworks make sure the configuration is correct by displaying "hello" on a webpage. That's it. No authentication, no file uploads, no POST requests, just a single GET request to show a string.

Note: the remainder of this post will be in Clojure, but the implementation language is just a detail. The idea is that this framework should be so simple, it can be ported to other languages in a few hours. Regarding Clojure - I had to choose a web server to get started, however, this is also just a detail, and the code shared should be portable across servers.

So, at this point our framework does nothing. Let's think about the simplest abstraction for what our web framework will do (remember - we need to transform text based on the request and maybe some state). We need our structure to be composable (linearly independent units that can be added together), flexible (order independent, interoperable), and efficient (fast, minimize blocking time with async). These units are commonly referred to as middleware.

Let's use a unit of work that is naturally composable - a function. Since functions take arguments, keep simplicity in mind and only accept one argument, a request. Now there is a concrete way to move forward - functions that each have some unit of work that they accomplish via a transformation to the request.

Here we define a function respond-hello with a single parameter "req". This function does not do anything with the request, but simply returns a 200 OK status with a text body of "hello".

Now, what functions should we make? Well, all we have is a request. We need to determine - where the request is going (routing), what type of request (GET, POST), and does the request need to persist some data (form)? Now how can we make structure these functions so they maintain maximum flexibility? Ideally the request will be piped though many functions until it is finally turned into a response and returned to the requester. Some functionality is needed by all requests - such as routing. Other functionality is only needed by certain requests - like authentication. It would be nice to have one central location for common middleware to transform the request, then other, less common middleware defined locally at each route or view.

To be continued...

TODOS:
  • Clojure
  • Keep it simple
  • Transformations on request
  • Copy/Paste framework, so no deps and cross language.

A few months ago, I decided to quit my job at PwC, to make time capsules on the internet a bigger thing. The idea sprouted when I reflected on why I didn't have more pictures with my dad. 10 years after he passed I still don't understand. Now-a-days when people pass away, they lose their digital belongings - unless they're meticulous in their will. Most people are not. So, the Facebook account stays up, the LinkedIn profile is still around, and that Dropbox with 10,000 special photos in it, is just, in limbo. This makes me incredibly sad as I reflect on my dad's life. His digital self is still around, but I can't access it. I can't access those incredible moments that I only care about now. Many people want those photos. But, there is no unified way for this to be accomplished - every online service has their own procedure.

The fragmentation of one's digital life becomes hard for family to tie together after death. So, how do time capsules play a role in this? Well, directly, they don't. But in the short term, there needs to be an attractive feature while people are healthy, so that they can be nudged to make better end of life plans. Time capsules are nothing new, but they have some appeal. In essence, it does the opposite of what Snapchat did. Document & Photo access appear after a period of time, rather than disappear. So, the hope is that people will be attracted with the novelty of setting a time capsule to deliver to a grandchild 50 years in the future, which will serve as an entry point into the service for modern estate planning.

That gave me inspiration to start making Life Box (name will likely change). It's the solution to a problem that is near and dear to me, but also extremely personal to everyone. Death is no fun, wills are no fun, nothing about the deal is fun. So why is there still so much friction to this thing that happens to everyone? That's a problem that I'm willing to tackle, because I just don't know if anyone else will try. Why are funerals expensive? Why is the funeral home trying to upsell me while I'm a wreck? Where does all my data go when I die? Honestly, who knows? As a tech person I don't even know what happens for any online services I use.

Life Box, while in its infancy, doesn't have a lot of capability to help with these questions, but the roadmap is clear, the fruit is hanging so low, I have no doubt there will be a few people who will use something to make this process just a little more bearable. Life Box is enticing people to come for the time capsules, but hoping they stay for the full-service estate planning & digital archival tool.

After a several month hiatus from Clojure, I'm finally back into it thanks to Advent of Code. It's reminding me just how much leverage you get by using Clojure.

This solution, while not performant, illustrates just how different the Clojure paradigm is from say Python. What's it doing? looperb takes two numbers than define a 6 digit range. We then loop over all of the numbers in that range, testing for monotonically increasing digits, and two successive digits that are identical. Looperb counts how many numbers qualify with that predicate.

Alternatively, this could be titled "Why Google kills so many products". I do not claim to be an economist or even an insider at Google. As for the numbers referenced here, only keep the magnitude in mind, they are not based on any published data. This was inspired by many scathing comments on Hacker News about the company's practice of killing off products. Here are my thoughts. First, consider a common engineering method.

Software engineers commonly make a prototype, get feedback either from users or metrics, then iterate. In software development this is a wonderful process because releasing to the world is easy and cheap. Development is the main expense.

As a product developer, or company, one seeks to lower costs and raise revenues, otherwise known a widening the profit margin. So, in software, this typically looks like lowering development costs, and acquiring more users of said software. The issue is that a lot of software has a somewhat fixed cost of development, so whether the software is used by 10 or 10,000,000, the development costs are the same. This brings us back to Google.

Simply put, the economics of software do not work in the favor of users of niche software made by a large organization. For Google, scaling to 10's of millions of users isn't the expense. Getting a product off of the ground, adding features, and fixing bugs is. So, here I (Google) am - 300 developers are tied up on a product that only has 50,000 users and isn't growing. However dedicated those users are, I (Google), as a profit maximizing entity, must immediately recognize this as a wasted resource, when we have many more products to launch and try to reach the holy-grail, hockey stick user growth.

Remember, Google doesn't make a ton of money per user of most products, so hitting the jackpot lottery is necessary to widen its margins. With high fixed development costs, and tiny marginal distribution costs, you must absolutely scale to millions of users rapidly or just wallow in low ROI land.

Wait...Aren't many of Google's loved products free? Yes, we have forgotten about the real economics here. Google needs your data. But, any data scientist or analyst would tell you that they don't need just your data, they need as many people's data as possible. Why? Statistic significance - Google needs to monetize millions of users at a time. When a product doesn't reach this scale, the data isn't as valuable since the aggregate can't be treated as significant (to Google anyways). Furthermore, there is the issue of how useful said data is, if it doesn't apply to a large portion of Google users. Somehow that data needs to be turned into advertising value, but if you don't have 100 million users of a data product, you have less of a value proposition for advertisers seeking very specific targets.

Software people appreciate iteration, but in Google's case, a lot of time iteration can mean its time to scrap a product. The key is that Google is a data company, not a message app or xyz company. Their key value proposition is just a ton of data, so if a particular product is free, and is lagging in the data creation department, it has to go. Google is iterating over products to find a data cash cow to monetize indirectly, but most companies are iterating on products to generate money directly.

Most of us aren't used to this. Many SaaS products we use are the bread and butter of the company who makes them. They would never drop their flagship product. Unfortunately, Google's flagship product is data, not any of these products . And so, we are left to greive with result of using products from a data company, rather than using products of a product company.

Since undergrad, my project structure would look something like:

    --- Number.java ---
  • print {...}
  • + {...}
  • toString {...}
    --- Int.java ---
  • print {...}
  • + {...}
  • toString {...}

Basically, each class would have the same 5 functions, with slightly different implementations to handle the peculiars of said class. The power of Clojure comes from only writing one class that can essentially take any data type and yield the proper result. Going through 4clojure.com, I see this power more and more with the test cases being different input data types, but the output just working. It's great.

  • Clojure
  • Call Option Pricing
  • Rust/Embedded
  • Elixir
  • WebAssembly
  • Soviet Russia
  • Limited Partnership Structure

If push notifications were made to push users away from notifications, I would say they are very effective. No, most people are fine with the bombardment of banner notifications and constant pings. I am not one of them.

In the last 3 years I have almost completely shut out all social apps, and for the ones I still have,there are no notifications besides the badge count. Effectively, I have all my attention back. It took a really, really long time for me to shun group chats, news, social media, and just about all forms of contact besides call and text. Interestingly, this practice has coincided with my most peaceful teen/adult years and I think there is a real reason for this.

A while back I moved my banking from Wells Fargo to Charles Schwab. The biggest reason being the constant fees at Wells, and the not so great investment options. Moving to Schwab was a breath of fresh air, absolutely no fees for banking, and they refund all ATM fees you incur! The brokerage account has much more to offer than Wells Fargo Advisors, so it just was all-around better. One thing I appreciate the most is that Schwab gives me the ability to directly buy T-bills, instead of being forced to use an account with Treasury like I had to do when I was at Wells Fargo. Right now, these typically yield 2 - 2.5% for bills that mature in under 6 months. It's perfect to use that as an emergency fund, as I don't miss out on interest, and bills are maturing and being reinvested on a rolling basis. The most I would need to wait for the bills to mature is a few weeks, rather than the comparable CD's that tie your money up for years at a time like a Private Equity fund, but yield only slightly better than T-bills.

Long story short, I recommend using Schwab, and I also recommend using the brokerage account(which is automatically opened in sync with Schwab checking) to buy T-bills in intervals so you can use it as emergency money. There are no transaction fees to do this, so it's a nice way to at least keep pace with inflation.

Since most of friends aren't CS people, they will not understand, but I wish they could. And I understand that saying this makes me a super nerd, but it's too amazing to ignore. Functional programming, e.g. Clojure, is blowing my mind. Coming from a background of heavy Java and Python in college,I learned that OOP is the only way, but now I feel as if my mind has expanded. For my non-tech friends, I wish I could port my pre-clojure technology skills to their brain, then introduce them to clojure so they could experience the awesome thing that is functional programming,but for now, posting it here will have to do :'-(

Clojure is amazing, especially coming from an OOP background. I feel like I'm doing next level/meta stuff, with ease, and I'm doing it in 10% of the text as a comparable Java or C# program.

How did I get here? news.ycombinator.com --> paulgraham.com --> "Learn LISP now!" --> SICP --> Scheme --> Ask HN for LISP learning peers --> start project in Clojure --> have free time at work --> here.

Over the past week, I have absorbed more naval content than I thought possible. From that, I have found Scott Adams and Kevin Simler, both of which will provide me with a lot of food for thought. I can't wait to digest both of their blogs. (link credit: Kevin Simler)

One of my favorite books, Antifragile, harps on the point of giving yourself asymmetric, non-linear outcomes. How? Well, you want to make sure you are in a position where the best case has nearly limitless gain, and the worst case is a 1x loss. I believe Naval Ravikant said something along these lines - he wants to play games where the best outcome is a 10,000x positive return, and the worst case is a 1x negative return. These concepts are extremely relevant for tech, venture capital, and options trading.

With those things being said, I want to shift my own portfolio, lifestyle, and career to capture these things. I believe by using long call options and tech I can maximize E[X]. Today, I will start on that journey and keep the blog updated with the results on a semi-regular basis, acknowledging that it might take 10+ years to pull away from the crowd.

Today I was playing with Robinhood's API(No official API exists), and I found this nice message at api.robinhood.com/marketdata

Typically, I think Spotify does a great job of introducing me to new music through the Discovery playlist and some others that are similar. I typically find artists that are smaller, that I have never heard of and I appreciate that. However, the other day someone brought Spotify's economics to my attention when they decide what to give you on these type of playlists. To Spotify, I'm sure they want me to enjoy the playlists, but they also want to push users to lower cost music, which would most likely be smaller artists that don't have expensive royalty fees. I've never thought about that, and the possible bias that introduces into the alogorithms that generate these playlists. Originally I could imagine Spotify's machine learning would optimize for song similarity and probability of a user adding it to their collection, but now I think there might be a more important optimization - cost. With all of that being said, the discovery playlists are still great, but some people have complaints about this fact.

For most of my life I believed in convictions, these truths of the world that exist only in black and white. Sometime around junior year of college, I began to question if they really were black and white or not. Now, I am only convicted that there are very few convictions to have in life.

It seems to me that the gig economy is inevitable at this point. One day we will get work assigned through API's, work flexible hours, and ultimately, do what we want.

Why is this inevitable? Well, three reasons: people want schedule flexibility, people want to work on personally meaningful things, and the current system kind of sucks.

What does a corporation do right now? Well, for most, the corporation just gives you a reason (social and financial) to do something you wouldn't choose to do, at a time(of day and year) you wouldn't choose to do it.

Right now, only (generally) lower-paying, service jobs like Uber and contracting work well under this model. Startups seem to be moving towards this gig style of work, with increasing remote work and vacation flexibility. Only time will tell.

Here are my favorite apps, websites, and software for finances.

Personal Banking: Charles Schwab -- weird choice right? Well, if you travel internationally with any frequency, or prolonged amount of time, it's hands down the best option as of this writing. The best features are unlimited, free ATM withdrawals at ANY ATM internationally, a decent account interest rate for a large bank, a good mobile app, and NO fees period. The downsides are no physical locations(so you are limited to interbank transfer, or mobile check deposit) and less appealing interest yields than some smaller banks. It's easier than you think to go all internet banking with Schwab, but it's nice to have a secondary bank account elsewhere to be able to deposit cash with the other bank then transfer to Schwab. Back to international banking: It's wonderful to avoid all service fees, overdraft fees, ATM fees, and international charge fees. Furthermore, when you make a transaction internationally, the exchange rate is extremely good, like they basically pass the VISA exchange rate directly to you with no markup. If having a physical presense is important to you, this is the next best option. The mobile deposit works extremely well, and they allow you "Add External Accounts", which lets you see your other banks' account balances, and make free transfers between the two!

Investing/Brokerage: Robinhood and Charles Schwab -- I recommend both because Robinhood is just so clean and simple(and free), and Schwab is so established, with a lot more to offer outside of the stock market. Robinhood is great, just great, if you have fun money, or like to check prices, but if you have a large portfolio, I would argue the app almost makes you instinctively a short term investor with bright red colors to make you sell on a bad day. Additionally, they have some interesting deals set up with High Frequency Trading firms like Citadel and Virtu which makes me think that you are getting pretty bad prices. I can't prove that, but they are the only big player offering free trading and they make more Payment for Order Flow than most brokerages. This probably only means anything if your trades are in the thousands of dollars, otherwise the bad prices probably are still better than dropping $5 or $10 at a traditional brokerage. Charles Schwab is cool because the have a cash sweep to take your uninvested cash and give you a small return(Robinhood takes that return for themselves), and they offer bonds, option strategies, CD's, and money markets, as well as foreign stocks. Schwab has modest trading fees for people with more capital, but if you just have a few thousand dollars, the fees will eat a non-negligible amount of your return.

Savings/Envelope/Retirement: Acorns -- Acorns is an app that is pretty simply, with small fees. the two products I like are Acorns Core, and Acorns Later. The Core account gets funded by one-time transfers, recurring transfers, or by "round ups". "Round ups" simply track your card purchases and round them up to the next dollar, transferring the difference to your Acorns account. This works really well for people who use their card a lot as it gives you a way to do yourself a favor for later by saving and investing more, the more you swipe. The Later account takes one-time transfers and recurring transfers, then allows you to select if you would like a Traditional or Roth IRA to invest them in. An important, distinguishing feature of the Core is that your investment options are streamlined into 5 options based on risk and exposure. You can look at the app to see exactly which percentage goes to which index fund or investment type. It is able to give you a relatively easy way to invest in index funds and still have a choice, but not be paralyzed by the number of funds available. Later, on the other hand has the same 5 categories, but it automatically puts you into the category based on your age. Younger age puts you in the "Aggressive" setting with mostly stocks, and older age puts you in the "Conservative" setting with more bonds.

Budgeting: You Need A Budget, aka YNAB -- Unlike this app's long name, the app is concise and simple to use. I have enjoyed using it for the past few days after months of struggling on Intuit's Mint. The key difference is Mint is free with advertisements, and YNAB is $7 a month. YNAB however has a much simpler UI, and even conceptually is simpler. Instead of just tracking and trying to self-limit expenses, you give every dollar a job(like enveloping). If one category runs out of money, you must pull funds from another category to use going forward. This helps you regulate and never overspend your overall budget, regardless of a sub-category staying in budget. YNAB imports all transactions directly from your bank or allows you to manually add if you would prefer. Ultimately Mint and YNAB differ in pricing, UI, and budget style. If you are squeezing by, then saving $7 a month and trying Mint would be worth it, otherwise, I think YNAB is a better budgeting style/solution.

  • Lenin's Tomb
  • Zero to One
  • Structure and Interpretation of Computer Programs
  • Chaos
  • Today, on Hacker News someone showed their new macOS app for tunneling a webapp to a url, and it jumpstarted my desire to do that for my webapp. I am hoping to try either ngrok(not new) or emporter.app to get my webapp online. I have enjoyed how repl.it allows this with minimal friction on their ide and I have wanted to do it for lifebox for some time.

    The past couple of days, I have spent so much time consuming information, mostly on Medium, Twitter, Farnam Street, and Hacker News. I have just been spending every moment I can taking in information. It makes me wonder if that is a net positive or if I am eating junk (brain) food.

    I am reasonably certain that the quality of Hacker News and Farnam Street is really good and well thought out, but the other two sources I am not as confident about. I am concerned that what I read on Medium is really just opinion pieces put out by the masses and packaged inside of intellectual lingo, but substantially lacking, on average. For example, I really enjoy Nassim Taleb and Naval Ravikant, and, previously, Signal v. Noise, but I find myself on the home page scrolling through random names and catchy titles and I just get the feeling that Medium isn't what I initially thought.

    Initially, I was attracted to the platform due to several bloggers (listed above), but as I created an account and eventually found myself reading other people's content, I wasn't very impressed. It seems that it is most likely a nice UI to dress up a bunch of BS articles, but nonetheless I still go there occasionally.

    What I'm really enjoying, although it is full of noise, is Twitter. I have curated a list of people that I follow and it really does seem to filter a lot of the noise that social media typically has. People still criticize Twitter for being a terrible platform with an unsucessful business model, but there is a ton of good content on there,and something special about the brevity of each tweet.

    Today I purchased barkparkdallas.com because I'm tired of going to the dog park by my house when it is muddy. I thought I could make a website to have other people post that it is muddy, then save their fellow dog owners some precious time.

  • Rework
  • Antifragile
  • Structure and Interpretation of Computer Programs
  • Poor Charlie's Almanac
  • Thinking Fast and Slow
  • TODO: Art of Programming
  • Today I spent most of my time on this website trying to get the little black bar formatted correctly so it would render and provide a small amount of help for readers when looking at my linear list of blog posts. It basically acts as an indicator for when one post starts and ends, and does nothing else special.

    It reminded me of how much disproportionate effort goes into design and UI, rather than html and content. This reminded me of the pareto principle - essentially 80% of this blog's content took 20% of my time. The other 80% of my time was spent on marginal changes.

    I can't remember how I found repl.it I think it had something to do with talking to my friends about some things I wanted to get done in 2019 - learning lisp was one of them. I think that led me to a google of best browser IDE's so I didn't have to install Scheme on my PC, and here we are.

    I ended up creating an account and started playing with Scheme. A couple of days later, i.e. today, as I am writing, I saw a link that you could host your own webpage on a repl subdomain and that seemed interesting. The appeal is this is much more simple than finding a bad wordpress service that one would have to pay $20 a year to use, then spend hours trying to get the formating and aesthetic right.

    I can appreciate how simple Paul Graham keeps his personal website, so I figured this could work well for me.
    (side note: his website is currently served over http, so repl blocks the redirect)

    Overall repl seems pretty legit and I can see myself making cool snippets on here in the future, but for now I plan to host a simple blog to complement my twitter activity.