As I pruned increasingly more dependencies, the few dependencies that desktop
and laptop hosted were too trivial for me to justify supporting. And so, I no
longer support them.
Support commonly used programs like fd, exa, bat, etc.
For now, I'm unsure how to manage the programs in my emacs/default.nix with my
home.nix. I'll wait until I have a stronger opinion to handle this.
Prefer starting lorri with home-manager.
Note: I could have removed the `systemctl --user start lorri.service` line
before switching to home-manager by calling `systemctl --user enable
lorri.service`. This would have made a symlink in
`~/.config/systemd/user/default.target.wants`.
I haven't used Tmux for months.
I also suspect that using the terminal in general may be a crutch. Ideally I
could replace everything I do in the terminal with Emacs analogues. Perhaps one
month I'll force myself to work without a terminal to see what happens.
While I do still technically own a Google cloudtop device, I haven't used it in
at least six months. In the interest of pruning non-critical dependencies, I'm
deleting it. I can alway restore it thanks to Git.
I didn't port everything from .ssh/config to home-manager. I omitted a few hosts
that I don't connect to anymore. I also omitted the `corp-ssh-helper`
configuration.
Today I wrote myself a custom fish prompt. It's mostly what I'd like, but I'd
like to finely tune it a bit. I'd like to create a separate repository to
release this. In that repository, I'll explain why I wrote this.
This problem challenged me: without using division, write a function that maps a
list of integers into a list of the product of every integer in the list except
for the integer at that index.
This was another greedy algorithm. The take-away is to first solve the problem
using brute force; this yields an algorithm with O(n*(n-1)) time
complexity. Instead of a quadratic time complexity, a linear time complexity can
be achieved my iterating over the list of integers twice:
1. Compute the products of every number to the left of the current number.
2. Compute the products of every number to the right of the current number.
Finally, iterate over each of these and compute lhs * rhs. Even though I've
solved this problem before, I used InterviewCake's hints because I was stuck
without them.
I should revisit this problem in a few weeks.
I'm considering this essay one of my favorites from Paul Graham. The essay
argues that good taste and bad taste exist. Graham argues against relativism in
design and cites a variety of examples of architecture, typography, writing,
sketching, painting, aircraft design, and others that bolster his opinion.
TL;DR - Design should strive to be:
- Simple: Prefer simplicity to complexity when possible.
- Timeless: Design today for tomorrow by pleasing yesterday.
- Pointed: Focus always on the problem; don't work for work's sake.
- Suggestive: Constrain usage without suffocating the user.
- Humorous: Prefer light-heartedness to sobriety.
- Difficult: "Good design" is takes time, effort, and tremendous skill.
- Ostensibly effortless: Solutions should look obviously correct.
- Symmetric Appreciate symmetry.
- Natural: In nature, form ever follows function.
- Iterative: Write; rewrite; rewrite; rewrite; throw away; write; publish.
- Imitative: Be confident enough to copy others' existing, beautiful ideas.
- Communal: Pay attention to "Schelling points" and join the party. Don't be the
Milanese Da Vinci.
- Fearless: Question the status quo; expect others to challenge your solution.
When I build socrates using `sudo nixos-rebuild [...] switch`, my
`nixos-config` (i.e. <briefcase/nixos/socrates/default.nix>) is a simple Nix
anonymous function. Typically readTree populates my pkgs, briefcase, depot
function parameters with <nixpkgs>, <briefcase>, <depot>, but `nixos-rebuild` is
unaware of `readTree`.
For now I'm manually importing these dependencies, and I'm leaving a TODO to
reconsider switching to the `{ pkgs, briefcase, ... }` style when I better
understand NixOS.
When I first created the monorepo, I borrowed @tazjin's monorepo's. I adapted
his depot/default.nix, replacing some of his paths with my paths. This worked
for me until recently.
I attemped to include <briefcase/monzo_ynab/job> as a systemd unit for my NixOS
machine, socrates. NixOS failed to build my changes, and I didn't fully
understand my default.nix since I borrowed most of it from @tazjin. I spent the
past week looking at the `fix` function. I realized that I didn't fully
understand how fixed-point recursion worked. This sent me down a rabbit hole
terminating with me studying the Y and Z combinators.
Ironically, after understanding the `fix` function, I realized that I didn't
need to use it where I was consuming it. I ended up pruning most of my
configuration, which resulted in this commit.
Yours truly,
lambda f: (lambda x: f(x(x)))(lambda x: f(x(x)))
Write a function that returns the highest product of three integers within a
list of integers. This solution uses a greedy algorithm that solves for the
answer in linear time. The space complexity is constant.
Write a function that returns the maximum profit that a trader could have made
in a day. I solved this using a greedy algorithm which constantly sets the
maximum profit by tracking the lowest price we've encountered.
Months ago when I was revisiting Nix, I decided to nixify my fish
configuration. This was a useful learning exercise. I've had two config.fish
files floating around this repository ever since then. I sometimes update one
and other times I update the other. I'm consolidating these files into one, so I
that this is no longer as issue.
Maybe this is my recency bias writing, but "Being Popular" may be one of my
favorite Paul Graham essays that I've read.
"Being Popular" outlines Paul Graham's ideas about what an ideal programming
language would look like. This essay took me 1-2 hours to read, but it was worth
the time.
Here are some quotes that I enjoyed (not sorted in any meaningful order):
"A friend of mine rarely does anything the first time someone asks him. He knows
that people sometimes ask for things that they turn out not to want. To avoid
wasting his time, he waits till the third or fourth time he's asked to do
something; by then, whoever's asking him may be fairly annoyed, but at least
they probably really do want whatever they're asking for."
"In this particular case there is a way to finesse our way out of the
problem. If we treat data structures as if they were functions on indexes, we
could write (a x y) instead, which is even shorter than the Perl form. Similar
tricks may shorten other types of expressions."
"The latest hot language, Python, is a watered-down Lisp with infix syntax and
no macros."
"Hackers would think a lot more highly of Lisp if Common Lisp had powerful
string libraries and good OS support."
"I think language designers would do better to consider their target user to be
a genius who will need to do things they never anticipated, rather than a
bumbler who needs to be protected from himself."
Some take-aways:
- Let's refer to Python as "Diet Lisp" from now until the end of time.
- Fight to keep your user-base small for as long as you can. Only fools want
large user bases.
- Rich Hickey definitely read this article; he took some ideas with him; he left
some ideas behind.
- Focus language design efforts around defining rich standard libraries,
especially for string manipulation.
- Worry little about supporting backwards compatibility; design a language that
can and is often rewritten.
- Shift the burden of optimizing code performance to the user by designing a
powerful runtime profiler that is tightly integrated into the language
runtime.
- Minimize the costs users face when experimenting: ensure that your language is
interactive; ensure users can create REPLs quickly.
- Support OS-level libraries (think about Go).
- Maximize introspection and hackability.
What a useful read!
I'd like to be able to call...
`nix-build -E '(import <briefcase> {}).nixos.socrates'`
...as part of my efforts to wane my dependence off of `nixos-rebuild`.
I'm not sure if this commit breaks everything in my monorepo. I think it
will.
Why am I doing this? Perhaps it's a bad idea. I don't fully understand how
readTree works. My ignorance is costing me hours of time spent debugging. In an
effort to better understand readTree, I'm removing the default values for my Nix
expression parameters, which I believe have preventing errors from surfacing.
At the moment, I don't think nixos-rebuild is reading $NIX_PATH, which
appropriately sets the paths for depot and briefcase. I'm going to explicitly
expose these values in the rebuild script for now.
After I considered the security implications of calling
`systemctl --user cat monzo-token-server`, I realized that monzo-token-server
should be a root service instead of a user service.
This service unit now also explicitly depends on briefcase.monzo_ynab.tokens,
which is a big improvement.
Paying off some tech debt. Instead of relying ./kv.json existing, which is
relative to the directory from which I start a program, I'm preferring that a
consumer explicitly provides this path.
"oneshot", according to `man systemd.service`, "will consider the unit up after
the main process exits". Since I designed token-server to run continuously, it
will not intentionally exit; therefore, systemd awaits its exit, which never
comes. "simple", on the other hand, does what I want.
Here is my first attempt to manage secrets when I deploy onto a NixOS machine.
Background: When I develop, I use direnv, which reads an .envrc file in which I
define my secrets. My secrets are read from `pass` using a pattern like this...
```shell
secret_value="$(pass show path/to/secret)"
```
...Thus far, I've found this pattern convenient. `pass show` invokes GPG, which
asks me for a password to authenticate. This means that when I cd into a
directory with an .envrc file using this pattern, I may be prompted by GPG for a
password. When I'm not, it's because gpg-agent is still caching my
password. This works for development, but I currently do not know how to use
direnv for deployments.
Here is what I'm using until I find a more convenient solution:
- Store the secrets in /etc/secrets on socrates. Ensure that the /etc/secrets
directory and its contents are only readable by root.
- Use systemd's Environment and NixOS's builtins.readFile to read the files in
/etc/secrets when I can `sudo nixos-rebuild`.
Ideally I could call a function like `builtins.readFromPasswordStore` within
configuration.nix. This would allow me to skip the step where I run...
```shell
> ssh socrates
> pass show finance/monzo/client-id | sudo tee /etc/secrets/monzo-client-id
> pass show finance/monzo/client-secret | sudo tee /etc/secrets/monzo-client-secret
> # etc
```
...I don't know how to manage secrets using NixOS, but at least this is one
answer.