diff options
Diffstat (limited to 'users/wpcarro/website/blog/content/english')
9 files changed, 966 insertions, 0 deletions
diff --git a/users/wpcarro/website/blog/content/english/caffeine.md b/users/wpcarro/website/blog/content/english/caffeine.md new file mode 100644 index 000000000000..9c3dbac0f120 --- /dev/null +++ b/users/wpcarro/website/blog/content/english/caffeine.md @@ -0,0 +1,5 @@ +--- +title: "Caffeine" +date: 2020-03-11T22:50:40Z +draft: true +--- diff --git a/users/wpcarro/website/blog/content/english/cell-phone-experiment.md b/users/wpcarro/website/blog/content/english/cell-phone-experiment.md new file mode 100644 index 000000000000..550ba4865ee0 --- /dev/null +++ b/users/wpcarro/website/blog/content/english/cell-phone-experiment.md @@ -0,0 +1,280 @@ +--- +title: "Cell Phone Experiment" +date: 2020-04-02T02:02:07Z +draft: false +--- + +### TL;DR + +I will not use my cell phone during March to learn more about how much I depend +on it. + +### Explore/Exploit + +Ever since I read Charles Duhigg's book, [The Power of Habit](poh), I try to +habituate as many aspects of my life as I can. + +Making my bed every morning is an example of a habit -- so too is flossing at +night before bed. + +The *exploit* axis of the [explore/exploit tradeoff](exp-exp) endows habits with +their power. Brian Christian and Tom Griffiths explain this concept more clearly +than I can in Chapter 2 of their exceptional book, [Algorithms to Live +By](algos). + +Habits are powerful, but if I overly exploit an activity, I may settle on a +local optimum in lieu of settling on a global optimum; these are the opportunity +costs of exploiting (i.e. habits) versus exploring (i.e. spontaneity). + +But what if it was possible to habituate exploration? + +### Monthly challenges + +Every month since October 2018, I challenge myself to try something new. In the +past, monthly challenges have been things like: +- sign up and take Brazilian Jiu Jitsu classes +- buy a guitar and learn [Freight Train](https://www.youtube.com/watch?v=IUK8emiWabU) +- study Italian +- learn a handstand + +Typically for an activity to qualify as a challenge, I must spend *at least +fifteen minutes* working on it *at least five days* each week. + +This month (i.e. March) I'm challenging myself to avoid using my cell phone. + +My parents gave me a cell phone when when I was a freshman in High School; I was +14 years old. I am now 28, so I have been using a cell phone semi-daily for over +a decade. + +While I enjoy the convenience that my cell phone provides me, I am curious to +suspend my usage to more clearly understand how much I depend on it... + +### April + +Now it is early April, and I completed March's challenge. So how was it? + +Below I outline the parts of using a cell phone that I missed and the parts that +I surprisingly did not miss. I will also mention the two times that I used my +cell phone and why. + +The first three things that I missed all relate to time. + +#### Timekeeping + +On the first day I realized that unless I was near a computer, I did not know +what time it was. + +I exclusively use my cell phone as my watch; I do not wear a watch. To adapt, I +started looking for clocks around my office and while I was taking public +transportation. Thankfully London posts the current time on the digital train +schedules. This oriented me while I was traveling, which was also when I needed +to know the time the most. + +Most of the month, however, I never precisely knew what time it was. + +#### Alarm clocks + +While I anticipated living without an alarm clock prior to the experiment, I +decided against buying a substitute. Prior to this month, I theorized that +morning alarms probably disrupt the quality of my sleep. If I'm tired, shouldn't +I keep sleeping? + +As the month progressed and my 24 hour day morphed into a 25 hour day, I learned +that I would prefer waking up at a set time every day and synchronize my +schedule with the rest of my timezone. + +I am still unsure if alarm clocks are helpful in the long-term. I would have +slept with the curtains drawn to allow the morning sun to wake me +up. Unfortunately, I live on the ground floor nearby a brightly shining street +lamp that spills into my bedroom. + +If I lived somewhere more remote (perhaps even a suburb would do) I would like +to repeat an experiment where I live for a month without an alarm clock. + +For now, I must return to the Temple of Chronology and supplicate until Father +Time restores my sanity. + +#### Timers + +Using timers motivates me to do a bunch of short tasks like cleaning my flat for +fifteen minutes, stretching, or reading before bed. Thankfully, I already owned +a physical timer that I keep in my kitchen. This replaced the timer on my phone +without disrupting my routine. + +#### Maps + +Speaking of being disoriented, what about living without maps software? On the +few occasions where I traveled somewhere that was unfamiliar to me, I had to +memorize the directions from my computer before I departed. + +At least I didn't need to visit gas stations or museums to buy trifold tourist +maps... + +I once left my office mistakenly assuming that I would download the directions +to my destination while commuting. As I awaited the office elevator, I realized +that I had no clue where I was heading. + +Thankfully I wasn't far from the safety, comfort, and familiarity of my desktop +computer -- with its fatty WiFi connection. In no time I was studying Google +Maps in my web browser and memorizing the directions. + +Overall this was hardly an inconvenience, and I think I even enjoyed +stress-testing my memory: a job that I so often outsource to hardware. + +#### Rendezvouses + +A couple of times I met friends in various parts of the city. Organizing these +particular rendezvouses was a novel (read: anachronistic) experience. For all +you young whippersnappers reading, take out your stone tablets and chisels. I'm +going to explain how this works: + +First I would tell my friends where and when to meet me. I emphasized that I +would be quite helpless to any changes they might make to the plans once I began +commuting, which made the commitments unusually more binding. + +On one occasion my friend -- who is characteristically prompt, and even chides +me for when I'm late -- was twenty minutes late for our engagement. My friend is +German, so I figured I should do my civic duty of alerting the German embassy +that my friend had broken German code, is obscenely late, and should therefore +hand-in his passport and renounce his citizenship. After awhile my conscience +advised me to reconsider. + +It was fortunate for both of us that I did not fully understand how late he was. +Remember: I didn't know what time it was. + +I decided this would be a useful opportunity to test my patience, so I loitered +for twenty minutes outside of our meeting point. He couldn't text me to tell me +that he was late. I couldn't listen to music, call family or friends, or partake +in any of the other rituals that modern-day loiterers observe to pass the +time. In the end he showed up, and it was scarcely a big deal. + +This experience made me wonder what the policy for abandoning plans is when +someone is running late. Before smart phones, how long did people wait? Maybe +the proper etiquette is to wait long enough for you to absolve yourself of the +guilt of flaking in the unlikely event that your friend arrives shortly after +you leave. + +So... thirty minutes? I'll call my grandma tomorrow and ask her. + +#### Boredom + +My phone couldn't entertain me while I queued at the grocery store. Same too +when I commuted. + +I also found myself listening to less music than I usually do. I decided to read +to occupy the void when I could; this helped me progress towards completing this +year's [GoodReads challenge][gr-annual]. + +### Cheating + +I used my phone twice during March. + +1. Once to use my bank's mobile app to internationally transfer money from my + U.K. account to my U.S. account. I could have used [TransferWise's][tw] + website, but I didn't. +2. Another time I used my phone to take pictures of an item that I wanted to + sell on [CraigsList][cl]. I could have and perhaps should have used my laptop's + webcam, but at the time, I didn't want to. I am accustomed to using my phone + to take pictures, and I wanted to sell something. + +In both of these cases, prior habits eroded my resolve to stay the course. These +are useful reminders that habits don't distinguish between helpful and hurtful; +they just exist. + +In total I would estimate that I spent somewhere around fifteen minutes using +my phone in March. While not perfect: + +> Better a diamond with a flaw than a pebble without (Confucius) + +### Substitution = Dilution + +While the explicit goal of this challenge was to avoid using my cell phone for a +month, the implicit goal was to disengage from many of the +[nonessential][essentialism] activities that compete for my attention. + +There were some activities that I didn't miss while living without a cell +phone. This wasn't because I don't value these activities, but rather because I +can adequately replace them with alternatives. + +For texting and making phone calls, I used [Telegram][wtf-telegram]. Telegram +helped me sustain a healthy relationship with my girlfriend while still honoring +the constraints of the challenge. + +While I appreciated the convenience Telegram provided, I felt that I remained +about as [available][wtf-availability] during March as I was in February. If I +ever experiment with drastically reducing my availability, I will be more +explicit about my objectives. + +### Distraction displacement (whack-a-mole) + +Because cell phones and other electronics have conditioned my behavior, I +habitually avoid boredom and seek entertainment. On its face this may not sound +like a harmful practice. My generation drills the aphorism "you only live once", +suggesting that we may want to embrace a Hedonistic lifestyle. + +Hedonism may or may not be a wise way to play the game of Life. All I know is +that living a life in which I am often stimulated but proportionately distracted +appeals increasingly less to me as time progresses. + +During March I noticed that once I freed my attention from sending/receiving +texts, my brain quickly reassigned my attention to maintaining a vigil over the +other social media outposts that I maintain. + +I should also admit that I habitually checked Telegram now that it served as my +new cell phone. Didn't see that coming... + +In another case, once I discovered that I could use Instagram in a web browser +instead of on my phone, I filled my newfound time and attention on +[Instagram.com][ig] (don't click!): displacing the time that I spent on an app +on my phone to time that I spent on a website in a web browser. + +Holy whack-a-mole! + +Halfway through the month, I wrote a [program to block websites][url-blocker] on +my computer. Surprisingly this worked and forced me to more deliberately fill +this hard-fought, foreign time with other activities. + +### Easy come, easy go? + +As the saying for making friends goes, "easy come, easy go", implying that +friendships that you easily form can just as easily be destroyed. + +Habits invert this creation/destruction relationship. In my experience "easy +come" implies "difficult to go". + +For example, I could easily form the habit of eating chocolate around 15:00 at +work; curbing this habit would require more effort. When I compare this to the +difficulty I experienced habituating a meditation practice, and how easily I +can dislodge my meditation practice, it seems to me that the laws of habits +dictate "easy come, difficult go; difficult come, easy go". + +I suspect that while my cravings for using a cell phone have temporarily ceased, +they will return shortly after I start using my cell phone. And as if nothing +happened, I return to where I was at the end of February just before I decided +to curb my cell phone usage. + +Because of this, I'm planning on keeping my cell phone in my closet where I +stored it during the month of March. As noted, enough substitutes exist for me +to live a mostly normal life: one where I am not unnecessarily straining the +relationships of my friends and my family. After all these are the people who +matter most to me and those who drive me to explore new ways to improve. + +I recognize that the "self" in self-experimentation is a misnomer. Can you truly +conduct an [N of 1 trial][nof1]? My decisions impact the people in my life, and +I want to thank everyone who tolerates my eccentric and oftentimes annoying +experimentation. + +Thank you for reading. + +[pod]: https://www.goodreads.com/book/show/12609433-the-power-of-habit +[exp-exp]: https://en.wikipedia.org/wiki/Multi-armed_bandit +[algos]: https://www.goodreads.com/book/show/25666050-algorithms-to-live-by +[gr-annual]: https://www.goodreads.com/user_challenges/19737920 +[cl]: http://craigslist.com +[tw]: https://transferwise.com +[url-blocker]: https://github.com/wpcarro/url-blocker +[wtf-telegram]: https://telegram.org +[wtf-availability]: https://landing.google.com/sre/sre-book/chapters/availability-table +[essentialism]: https://www.goodreads.com/book/show/18077875-essentialism +[ig]: https://instagram.com +[nof1]: https://en.wikipedia.org/wiki/N_of_1_trial diff --git a/users/wpcarro/website/blog/content/english/lets-learn-nix-caching.md b/users/wpcarro/website/blog/content/english/lets-learn-nix-caching.md new file mode 100644 index 000000000000..a436d4de25eb --- /dev/null +++ b/users/wpcarro/website/blog/content/english/lets-learn-nix-caching.md @@ -0,0 +1,49 @@ +--- +title: "Lets Learn Nix Caching" +date: 2020-03-17T18:05:38Z +draft: true +--- + +## TL;DR + +1. I use `NixOS/nixpkgs-channels` instead of `NixOS/nixpkgs` and avoid + `nix-channel`. + +## More information + +- By default the Nix package manager uses cache.nixos.org as a binary cache. +- Visit status.nixos.org +- `git clone git@github.com:NixOS/nixpkgs-channels` instead of + `NixOS/nixpkgs`. The former mirrors the latter and uses Git branches to track + the published channels. + +## What is a Nix channel + +If you run... + +```shell +$ git clone git@github.com:NixOS/nixpkgs ~/nixpkgs +$ export NIX_PATH="nixpkgs=$(realpath ~/nixpkgs)" +``` + +One benefit to cloning nixpkgs is that you can browse the source code on your +machine using tools like `git` and `emacs`. You can also experimentally patch +and test Nix code this way. + +If any of the above appeals to you, clone `nixpkgs-channels` instead. + +The Nix maintainers build and test the commits from `nixpkgs` using Hydra. Tests +include reproducibility tests, etc. + +Various channels have different verification phases. + +The cache at cache.nixos.org is populate the cache at cache.nixos.org. + +You want to increase the likelihood that you are hitting this cache. For +example, `google-chrome` takes hours to build. + +## What is a binary cache? + +## What is Hydra (Nix CI)? + +## What is Cachix? diff --git a/users/wpcarro/website/blog/content/english/lets-learn-nix-determinism-vs-reproducibility.md b/users/wpcarro/website/blog/content/english/lets-learn-nix-determinism-vs-reproducibility.md new file mode 100644 index 000000000000..2e12a6b06fcc --- /dev/null +++ b/users/wpcarro/website/blog/content/english/lets-learn-nix-determinism-vs-reproducibility.md @@ -0,0 +1,121 @@ +--- +title: "Lets Learn Nix: Reproducibility" +date: 2020-03-17T12:06:47Z +draft: true +--- + +I am dedicating this page to defining and disambiguating some terminology. I +think it is important to use these terms precisely, so it may be worthwhile to +memorize these definitions and ensure that you are clarifying the discourse +rather than muddying it. + +## Terms + +- repeatable build: +- reproducible build: +- deterministic build: +- pure function: +- impure function: +- idempotent function: + +TODO(wpcarro): Consistently and deliberately use reproducible and +deterministic. + +## Repeatable vs. Reproducible + +Is NixOS reproducible? Visit [@grhmc][who-grhmc]'s website, +[r13y.com](https://r13y.com), to find out. + +At the time of this writing, 1519 of 1568 (i.e. 96.9%) of the paths in the +`nixos.iso_minimal.x86_64-linux` installation image are reproducible. + +## What hinders reproducibility? + +Timestamps. + +If package A encodes a timestamp into its build artifact, then we can +demonstrate that package A is *not reproducible* simply by building it at two +different times and doing a byte-for-byte comparison of the build artifacts. + +## Does Nix protect developers against non-determinism + +Yes. But not entirely. How? + +## Deterministic Nix derivation + +```nix +{ pkgs ? import <nixpkgs> {}, ... }: + +with pkgs; + +stdenv.mkDerivation { + name = "reproducible"; + phases = [ "buildPhase" ]; + buildPhase = "echo reproducible >$out"; +} +``` + +## Non-deterministic Nix derivation + +We can introduce some non-determinism into our build using the `date` function. + +```nix +# file: /tmp/test.nix +{ pkgs ? import <nixpkgs> {}, ... }: + +with pkgs; + +stdenv.mkDerivation { + name = "non-reproducible"; + phases = [ "buildPhase" ]; + buildPhase = "date >$out"; +} +``` + +Then run... + +```shell +$ nix-build /tmp/test.nix +$ nix-build /tmp/test.nix --check --keep-failed +``` + +## How do you test reproducibility? + +We can use `cmp` to compare files byte-for-byte. The following comparison should +fail: + +```shell +$ echo foo >/tmp/a +$ echo bar >/tmp/b +$ cmp --silent /tmp/{a,b} +$ echo $? +``` + +And the following comparison should succeed: + +```shell +$ echo hello >/tmp/a +$ echo hello >/tmp/b +$ cmp --silent /tmp/{a,b} +$ echo $? +``` + +## Reproducible vs. deterministic + +Reproducible builds *are* deterministic builds and deterministic build + +## Deterministic, Reproducible, Pure, Idempotent, oh my + +- A pure function has no side-effects. + +- An idempotent function can be executed more than once with the same arguments + without altering the side-effects. + +- A deterministic function ensures that + +## Deterministic vs. Reproducible + +I can check if a build is reproducible using [these tools][wtf-repro-tools]. + +[wtf-repro-tools]: https://reproducible-builds.org/tools/ +[who-grhmc]: https://twitter.com/grhmc diff --git a/users/wpcarro/website/blog/content/english/lets-learn-nix-dotfiles.md b/users/wpcarro/website/blog/content/english/lets-learn-nix-dotfiles.md new file mode 100644 index 000000000000..084fb19e4406 --- /dev/null +++ b/users/wpcarro/website/blog/content/english/lets-learn-nix-dotfiles.md @@ -0,0 +1,401 @@ +--- +title: "Let's Learn Nix: Dotfiles" +date: 2020-03-13T22:23:02Z +draft: true +--- + +## Let's Learn Nix: Dotfiles + +### Dependencies + +Speaking of dependencies, here's what you should know before reading this tutorial. + +- Basic Nix syntax: Nix 1p + +What version of Nix are we using? What version of `<nixpkgs>` are we using? What +operating system are we using? So many variables... + +Cartesian product of all possibilities... + +TODO(wpcarro): Create a graphic of the options. + +### The problems of dotfiles + +How do you manage your dependencies? + +You can use `stow` to install the dotfiles. + +### home-manager + +What we are going to write is most likely less preferable to the following +alternatives: +- using Nix home-manager +- committing your `.gitconfig` into your + +In the next tutorial, we will use [home-manager][wtf-home-mgr] to replace the +functionality that we wrote. + +So why bother completing this? + +### Let's begin + +Welcome to the first tutorial in the [Let's Learn Nix][wtf-lln] series. Today we +are going to create a Nix derivation for one of your dotfiles. + +"Dotfiles" refers to a user's collection of configuration files. Typically these +files look like: +- `.vimrc` +- `.xsessionrc` +- `.bashrc` + +The leading "dot" at the beginning gives dotfiles their name. + +You probably have amassed a collection of dotfiles whether or not you are +aware. For example, if you use [git][wtf-git], the file `~/.gitconfig` should +exist on your machine. You can verify this with: + +```shell +$ stat ~/.gitconfig +``` + +When I was first learning `git`, I learned to configure it using commands I +found in books and tutorials that often looked like: + +```shell +$ git config user.email +``` + +The `~/.gitconfig` file on your machine may look something like this: + +```.gitconfig +[user] + name = John Cleese + email = john@flying-circus.com + username = jcleese +[core] + editor = emacs +[web] + browser = google-chrome +[rerere] + enabled = 1 + autoupdate = 1 +[push] + default = matching +[color] + ui = auto +[alias] + a = add --all + ai = add -i + b = branch + cl = clone + cp = cherry-pick + d = diff + fo = fetch origin + lg = log --oneline --graph --decorate + ps = push + pb = pull --rebase + s = status +``` + +As I ran increasingly more `git config` commands to configure my `git` +preferences, the size of my `.gitconfig` increased, and the less likely I was to +remember which options I set to which values. + +Thankfully a coworker at the time, Ryan ([@rschmukler][who-ryan]), told me that +he version-controlled his `.gitconfig` file along with his other configuration +files (e.g. `.vimrc`) in a repository he called "dotfiles". + +Version-controlling your dotfiles improves upon a workflow where you have a +variety of configuration files scattered around your machine. + +If you look at the above `.gitconfig`, can you spot the dependencies? + +We explicitly depend `emacs` and `google-chrome`. We also *implicitly* depend on +`git`: there is not much value of having a `.gitconfig` file if you also do not +have `git` installed on your machine. + +Dependencies: +- `emacs` +- `google-chrome` + +Let's use Nix to generate this `.gitconfig` file. Here is what I would like our +API to be: + +Let's create a file `gitconfig.nix` and build our function section-by-section: + +TODO(wpcarro): Link to sections here +- options.user +- options.core +- options.web +- options.rerere +- options.push +- options.color +- options.alias + +```shell +$ touch gitconfig.nix +``` + +### options.user + +```haskell +AttrSet -> String +``` + +```nix +user = { + name = "John Cleese"; + email = "john@flying-circus.com"; + username = "jcleese"; +}; +``` + +```.gitconfig +[user] + name = John Cleese + email = john@flying-circus.com + username = jcleese +``` + +### options.core + +```nix +core = { + editor = "${pkgs.emacs}/bin/emacs"; +}; +``` + +```.gitconfig +[core] + editor = /nix/store/<hash>-emacs-<version>/bin/emacs +``` + +### options.web + +```nix +web.browser = "${pkgs.google-chrome}/bin/google-chrome"; +``` + +```.gitconfig +[web] + browser = /nix/store/<hash>-google-chrome-<version>/bin/google-chrome +``` + +### options.rerere + +```nix +rerere = { + enabled = true; + autoupdate = true; +}; +``` + +```.gitconfig +[rerere] + enabled = 1 + autoupdate = 1 +``` + +### options.push + +```nix +push.default = "matching"; +``` + +```.gitconfig +[push] + default = matching +``` + +### options.color + +```nix +color.ui = "auto"; +``` + +```.gitconfig +[color] + ui = auto +``` + +We need to define a function named `gitconfig` that creates a Nix [derivation][wtf-derivation]: + +```nix +# file: gitconfig.nix +let + # Import the <nixpkgs> package repository. + pkgs = import <nixpkgs> {}; + + # Stringify the attribute set, `xs`, as a multilined string formatted as "<key> = <value>". + # See attrsets.nix for more functions that work with attribute sets. + encodeAttrSet = xs: lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k} = ${v}") xs); + + # Define out function name `gitconfig` that accepts an `options` argument. + gitconfig = options: pkgs.stdenv.mkDerivation { + # The gitconfig file that Nix builds will be located /nix/store/some-hash-gitconfig. + name = "gitconfig"; + src = pkgs.writeTextFile ".gitconfig" '' + [user] + name = ${options.user.name} + email = ${options.user.email} + username = ${options.user.username} + [core] + editor = ${options.core.editor} + [web] + editor = ${options.web.browser} + [rerere] + enabled = ${if options.rerere.enabled "1" else "0"} + autoupdate = ${if options.rerere.autoupdate "1" else "0"} + [push] + default = ${options.push.default} + [color] + ui = ${options.color.ui} + [alias] + ${encodeAttrSet options.aliases} + ''; + buildPhase = '' + ${pkgs.coreutils}/bin/cp $src $out + ''; + installPhase = '' + ${pkgs.coreutils}/bin/ln -s $out ~/.gitconfig + ''; + }; +} in gitconfig { + user = { + name = "John Cleese"; + email = "john@flying-circus.com"; + username = "jcleese"; + }; + core = { + editor = "${pkgs.emacs}/bin/emacs"; + }; + web.browser = "${pkgs.google-chrome}/bin/google-chrome"; + rerere = { + enabled = true; + autoupdate = true; + }; + push.default = "matching"; + color.ui = "auto"; + aliases = { + a = "add --all"; + ai = "add -i"; + b = "branch"; + cl = "clone"; + cp = "cherry-pick"; + d = "diff"; + fo = "fetch origin"; + lg = "log --oneline --graph --decorate"; + ps = "push"; + pb = "pull --rebase"; + s = "status"; + }; +} +``` + +### options.alias + +We want to write a function that accepts an attribute set and returns a +string. While Nix is a dynamically typed programming language, thinking in types +helps me clarify what I'm trying to write. + +```haskell +encodeAttrSet :: AttrSet -> String +``` + +I prefer using a Haskell-inspired syntax for describing type signatures. Even if +you haven't written Haskell before, you may find the syntax intuitive. + +Here is a non comprehensive, but demonstrative list of example type signatures: +- `[String]`: A list of strings (i.e. `[ "cogito" "ergo" "sum" ]`) +- `AttrSet`: A nix attribute set (i.e. `{ name = "John Cleese"; age = 80; }`). +- `add :: Integer -> Integer -> Integer`: A function named `add` that accepts + two integers and returns an integer. + +Specifically, we want to make sure that when we call: + +```nix +encodeAttrSet { + a = "add --all"; + b = "branch"; +} +``` + +...it returns a string that looks like this: + +```.gitconfig +a = "add --all" +b = "branch" +``` + + +TODO(wpcarro): @tazjin's nix-1p mentions this. Link to it. +Nix has useful functions scattered all over the place: +- `lib.nix` +- `list.nix` +- `lib.attrSet` + +But I cannot recall exactly which functions we will need to write +`encodeAttrSet`. In these cases, I do the following: +1. Run `nix repl`. +2. Browse the Nix source code. + +Google "nix attribute sets" and find the Github link to `attrsets.nix`. + +You should consider repeating this search but instead of searching for +"attribute sets" search for "lists" and "strings". That is how I found the +functions needed to write `encodeAttrSet`. Let's return to our `nix repl`. + +Load the nixpkgs set: + +```nix +nix-repl> :l <nixpkgs> +Added 11484 variables. +``` + +Define a test input called `attrs`: + +```nix +nix-repl> attrs = { fname = "John"; lname = "Cleese"; } +``` + +Map the attribute set into `[String]` using `lib.mapAttrsToList`: + +```nix +nix-repl> lib.mapAttrsToList (k: v: "${k} = ${toString v}") attrs +[ "fname = John" "lname = Cleese" ] +``` + +Now join the `[String]` together using `lib.concatStringsSep`: + +```nix +nix-repl> lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k} = ${v}") attrs) +"fname = John\nlname = Cleese" +``` + +Now let's use this to define our function `encodeAttrSet`: + +```nix +# file: gitconfig.nix +encodeAttrSet = xs: lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${k} = ${v}") xs); +``` + +### Using nixpkgs search + +[Nixpkgs search][wtf-nixpkgs-search]. + +### Conclusion + +We learned how to help ourselves. + +- Where does `emacs` exist? What about `google-chrome`? [nixpkgs search][wtf-nixpkgs-search] +- Verify that I have it? [nix REPL][using-nix-repl] + +We used Nix to create our first derivation. + +[wtf-lln]: /lets-learn-nix +[wtf-git]: https://git-scm.com/ +[wtf-derivation]: https://nixos.org/nixos/nix-pills/our-first-derivation.html +[wtf-nixpkgs-search]: https://nixos.org/nixos/packages.html?channel=nixos-19.09 +[using-nix-repl]: /using-the-nix-repl +[wtf-home-mgr]: https://github.com/rycee/home-manager +[who-ryan]: https://twitter.com/rschmukler diff --git a/users/wpcarro/website/blog/content/english/lets-learn-nix-tutorial-reproducibility.md b/users/wpcarro/website/blog/content/english/lets-learn-nix-tutorial-reproducibility.md new file mode 100644 index 000000000000..c80892164dbe --- /dev/null +++ b/users/wpcarro/website/blog/content/english/lets-learn-nix-tutorial-reproducibility.md @@ -0,0 +1,41 @@ +--- +title: "Lets Learn Nix: Tutorial Reproducibility" +date: 2020-03-17T18:34:58Z +draft: true +--- + +## Install Nix + +Link to nixos page. + +## The rest + +Start with this... + +```shell +$ mkdir ~/lets-learn-nix +$ cd ~/lets-learn-nix +``` + +...done. Copy the following and paste it into a file name `shell.nix`. + +```nix +# file: shell.nix +let + pkgs = import (builtins.fetchGit { + url = "https://github.com/NixOS/nixpkgs-channels"; + ref = "refs/heads/nixos-19.09"; + }) {} +in pkgs.mkShell { + buildInputs = with pkgs; [ + git + ]; + NIX_PATH = "nixpkgs=${pkgs}"; +}; +``` + +...then... + +```shell +$ nix-shell +``` diff --git a/users/wpcarro/website/blog/content/english/lets-learn-nix.md b/users/wpcarro/website/blog/content/english/lets-learn-nix.md new file mode 100644 index 000000000000..a7c9a22e422e --- /dev/null +++ b/users/wpcarro/website/blog/content/english/lets-learn-nix.md @@ -0,0 +1,58 @@ +--- +title: "Lets Learn Nix" +date: 2020-03-13T21:50:47Z +draft: false +--- + +## Background + +[Nix][wtf-nix] may be the most useful tool that I use. I consider it as valuable +as [Git][wtf-git] or [Emacs][wtf-emacs]. My friend, David ([@dmjio][who-dmjio]), +first introduced me to Nix when we worked together at a Haskell startup in +NYC. Before this, I had been managing my system configuration using software +that I wrote -- first in Bash, then in Python, then in Golang. + +It took me awhile to understand Nix. I left the NYC startup, joined Google, and +relocated to London. Here I met another Nix-enlightened monk, Vincent +([@tazjin][who-tazjin]), who patiently taught me enough Nix to become +self-reliant and productive. + +Many resources exist to learn Nix; the Nix community on IRC continues to help me +and others effectively use Nix. I'm creating this series to write the tutorials +that I would have found useful when I started learning Nix. If you are just +beginning your Nix journey, I hope these tutorials help you. + +## Goals + +I aim to make each tutorial in the "Let's Learn Nix" series: +- Actionable: Readers will be writing code. +- Digestible: Readers should be able to finish each tutorial in fifteen minutes. +- Reproducible: Readers should expect the output of their code to match what + these tutorials claim they should see. + +## About the author + +My name is William ([@wpcarro][who-wpcarro]). My three favorite tools are Git, +Emacs, and Nix. I am an American expat currently working at Google in +London. While during the day I primarily write Java, Python, and TypeScript, I +prefer functional programming. I use Nix to deploy software and manage the +multiple machines across which I work. + +## Let's Begin + +Before we get started, Nix is a programming language. To familiarize yourself +with the syntax, semantics, and idioms, consider reading this brief [Nix One +Pager][nix-1p]. I recommend keeping it around as a reference. + +When I was first learning Nix, I wanted to use it to manage my dotfiles. Our +first tutorial will help you get started: [Let's Learn Nix: +Dotfiles][lln-dotfiles] + +[wtf-nix]: https://nixos.org +[wtf-git]: https://git-scm.com +[wtf-emacs]: https://www.gnu.org/software/emacs +[who-dmjio]: https://twitter.com/dmjio +[who-tazjin]: https://twitter.com/tazjin +[who-wpcarro]: https://twitter.com/wpcarro +[lln-dotfiles]: /lets-learn-nix-dotfiles +[nix-1p]: https://github.com/tazjin/nix-1p diff --git a/users/wpcarro/website/blog/content/english/nix-and-hugo.md b/users/wpcarro/website/blog/content/english/nix-and-hugo.md new file mode 100644 index 000000000000..ff0fe70205da --- /dev/null +++ b/users/wpcarro/website/blog/content/english/nix-and-hugo.md @@ -0,0 +1,5 @@ +--- +title: "Deploy Hugo blog with Nix" +date: 2020-03-11T18:42:32Z +draft: true +--- diff --git a/users/wpcarro/website/blog/content/english/self-hosting.md b/users/wpcarro/website/blog/content/english/self-hosting.md new file mode 100644 index 000000000000..1705541d820c --- /dev/null +++ b/users/wpcarro/website/blog/content/english/self-hosting.md @@ -0,0 +1,6 @@ +--- +title: "Self Hosting" +date: 2020-03-11T22:53:56Z +draft: true +--- + |