~ben/web

8065a3e91ecb96efb198f2e4304772f4f9ba2e02 — Ben Sima 11 months ago 544101d
convert clog articles to org
20 files changed, 1855 insertions(+), 1293 deletions(-)

D clog/git-good.md
A clog/git-good.org
D clog/how-i-learned-monads.md
A clog/how-i-learned-monads.org
D clog/learning-clojure.md
A clog/learning-clojure.org
D clog/perl-sunrise.md
A clog/perl-sunrise.org
D clog/refactor-pattern-matching.md
A clog/refactor-pattern-matching.org
D clog/robust-clojure-nil.md
A clog/robust-clojure-nil.org
D clog/server-tools.md
A clog/server-tools.org
D clog/sql-yesod-persistent.md
A clog/sql-yesod-persistent.org
D clog/strangeloop-2017.md
M index.org
M now.org
M resume.org
D clog/git-good.md => clog/git-good.md +0 -114
@@ 1,114 0,0 @@
---
title: Git Good
date: 2019-02-04
tldr: A friendly guide to matering git.
---

> _This is a starting point for mastering git, a sisyphean task no
> doubt. Git is a complex software, nobody is expected to master
> **all** of it, so if you have a useful tip, please share!_

The git manual pages are actually very good. Start with `man git` and
maybe check out `man gittutorial`. Don't be shy about using `man
git-<subcommand>` when you don't know how to do something. If you're
curious about different ways to use git in your daily workflow, check
out `man gitworkflows`.

# Guidelines

- <a name="small-commits"></a>
Separate commits into small, logical changes. [Avoid large diffs as much as possible.](https://medium.com/@kurtisnusbaum/large-diffs-are-hurting-your-ability-to-ship-e0b2b41e8acf#.n2fbjcuob)
<sup>[link](#small-commits)</sup>

- <a name="commit-msg"></a>
In a commit message, the first line is a brief _what_, the rest is a succint
_why_.
<sup>[link](#commit-msg)</sup>

- <a name="wrap-lines"></a>
In commit messages, limit the first line to 50 characters, wrap the rest to 80 characters.
<sup>[link](#wrap-lines)</sup>

# Grokking Git

## Rebasing: the most important concept

I once read an interview with Linus where he said that every git command is
basically a different take on `rebase`. So, if you want to get good at git
quick, learn about rebasing - the rest will follow.

- [Git Book chapter on rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
- [Ryan's tutorial](http://rypress.com/tutorials/git/rebasing)
- [Rebase as an alternative to merge](https://www.youtube.com/watch?v=PnHlnx_nmCI) [video]
- [Don't be scared of git rebase][leclaire]

[leclaire]: https://nathanleclaire.com/blog/2014/09/14/dont-be-scared-of-git-rebase/

## Branching

- [Learn git branching](http://learngitbranching.js.org/) - awesome interactive tutorial

# Tools

Git isn't perfect. These tools make it easier to work with:

- [GitHub Desktop](https://desktop.github.com/)
- [Magit](https://magit.vc/) (emacs package)
- [gitgutter](https://github.com/airblade/vim-gitgutter) (vim plugin)
- [fugitive](https://github.com/tpope/vim-fugitive) (vim plugin)

# Commit Messages

**Original article:** [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/)

Git was originally used over email: someone would make a change to some
software, create a `.patch` file, and email it to the maintainer. In the email,
the author of the patch would add an appropriate subject with a brief line about
*what* the patch does, and then in the body they would explain _why_ the patch
is a good idea.

Commit messages retain this structure: the first line is a brief _what_, the
rest is a succint _why_.

## Seven Rules to Good Commit Messages

I guess they're really more like [guidelines](https://www.youtube.com/watch?v=jl0hMfqNQ-g)...

1. Separate subject from body with a blank line
1. Limit the subject line to 50 characters
1. Capitalize the subject line
1. Do not end the subject line with a period
1. Use the imperative mood in the subject line
1. Wrap the body at 72 characters
1. Use the body to explain what and why vs. how

## Automate Good Commit Messages with `.gitmessage`

Originally created by [David Winterbottom][david], this is a quick
hack to make you more likely to write helpful commit messages.

[david]: http://codeinthehole.com/writing/a-useful-template-for-commit-messages/

Save the following as `~/.gitmessage`:

```
# If applied, this commit will...


# Why was this change made?


# Any references to tickets, articles, etc?
```

Then, add the following to `~/.gitconfig`:

```
[commit]
  template = ~/.gitmessage
```

# Other References & Tutorials

- [Git Magic](http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html)
- [Drew Devault's _Tips for a disciplined git workflow_](https://drewdevault.com/2019/02/25/Using-git-with-discipline.html)

A clog/git-good.org => clog/git-good.org +143 -0
@@ 0,0 1,143 @@
#+title: Git Good
#+date: 2019-02-04
#+subtitle: A friendly guide to matering git.

#+BEGIN_QUOTE
/This is a starting point for mastering git, a sisyphean task no
doubt. Git is a complex software, nobody is expected to master *all*
of it, so if you have a useful tip, please share!/
#+END_QUOTE

The git manual pages are actually very good. Start with =man git= and
maybe check out =man gittutorial=. Don't be shy about using
=man git-<subcommand>= when you don't know how to do something. If
you're curious about different ways to use git in your daily workflow,
check out =man gitworkflows=.

* Guidelines
:PROPERTIES:
  :CUSTOM_ID: guidelines
  :ID:       89a78e5d-8717-43b1-aeee-af09157aa6d9
  :END:

- Separate commits into small, logical changes. [[https://medium.com/@kurtisnusbaum/large-diffs-are-hurting-your-ability-to-ship-e0b2b41e8acf#.n2fbjcuob][Avoid large diffs as much as
  possible.]]

- In a commit message, the first line is a brief /what/, the rest is a succint
  /why/.

- In commit messages, limit the first line to 50 characters, wrap the rest to 80
  characters.

* Grokking Git
:PROPERTIES:
  :CUSTOM_ID: grokking-git
  :ID:       c5184ad5-046e-43b4-ba78-d195381eec8b
  :END:

** Rebasing: the most important concept
:PROPERTIES:
   :CUSTOM_ID: rebasing-the-most-important-concept
   :ID:       35c10fe9-4f80-44ce-a287-4bbedbc13ce9
   :END:

I once read an interview with Linus where he said that every git command is
basically a different take on =rebase=. So, if you want to get good at git
quick, learn about rebasing - the rest will follow.

- [[https://git-scm.com/book/en/v2/Git-Branching-Rebasing][Git Book chapter on rebasing]]
- [[http://rypress.com/tutorials/git/rebasing][Ryan's tutorial]]
- [[https://www.youtube.com/watch?v=PnHlnx_nmCI][Rebase as an alternative to merge]] [video]
- [[https://nathanleclaire.com/blog/2014/09/14/dont-be-scared-of-git-rebase/][Don't be scared of git rebase]]

** Branching
:PROPERTIES:
   :CUSTOM_ID: branching
   :ID:       aac931e0-e71c-41fd-87b8-8a84e2924614
   :END:

- [[http://learngitbranching.js.org/][Learn git branching]] - awesome interactive tutorial

* Tools
:PROPERTIES:
  :CUSTOM_ID: tools
  :ID:       104b807f-88a2-4749-a166-424caaffb8bc
  :END:

Git isn't perfect. These tools make it easier to work with:

- [[https://desktop.github.com/][GitHub Desktop]]
- [[https://magit.vc/][Magit]] (emacs package)
- [[https://github.com/airblade/vim-gitgutter][gitgutter]] (vim plugin)
- [[https://github.com/tpope/vim-fugitive][fugitive]] (vim plugin)

* Commit Messages
:PROPERTIES:
  :CUSTOM_ID: commit-messages
  :ID:       77058ae7-e462-4ce6-a452-800b73a6fcf8
  :END:

*Original article:* [[http://chris.beams.io/posts/git-commit/][How to Write a Git Commit Message]]

Git was originally used over email: someone would make a change to some
software, create a =.patch= file, and email it to the maintainer. In the email,
the author of the patch would add an appropriate subject with a brief line about
/what/ the patch does, and then in the body they would explain /why/ the patch
is a good idea.

Commit messages retain this structure: the first line is a brief /what/, the
rest is a succint /why/.

** Seven Rules to Good Commit Messages
:PROPERTIES:
   :CUSTOM_ID: seven-rules-to-good-commit-messages
   :ID:       e6d4c204-64a3-40ed-9b11-318fb120a2fb
   :END:

I guess they're really more like [[https://www.youtube.com/watch?v=jl0hMfqNQ-g][guidelines]]...

1. Separate subject from body with a blank line
2. Limit the subject line to 50 characters
3. Capitalize the subject line
4. Do not end the subject line with a period
5. Use the imperative mood in the subject line
6. Wrap the body at 72 characters
7. Use the body to explain what and why vs. how

** Automate Good Commit Messages with =.gitmessage=
:PROPERTIES:
   :CUSTOM_ID: automate-good-commit-messages-with-.gitmessage
   :ID:       b1558a38-d4cb-46f9-8407-b2888266c016
   :END:

Originally created by [[http://codeinthehole.com/writing/a-useful-template-for-commit-messages/][David Winterbottom]], this is a quick hack to make you more
likely to write helpful commit messages.

Save the following as =~/.gitmessage=:

#+BEGIN_EXAMPLE
# If applied, this commit will...


# Why was this change made?


# Any references to tickets, articles, etc?

#+END_EXAMPLE

Then, add the following to =~/.gitconfig=:

#+BEGIN_EXAMPLE
[commit]
template = ~/.gitmessage
#+END_EXAMPLE

* Other References & Tutorials
:PROPERTIES:
  :CUSTOM_ID: other-references-tutorials
  :ID:       527bd89b-c74f-47df-9705-4fc7c612d551
  :END:

- [[http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html][Git Magic]]
- [[https://drewdevault.com/2019/02/25/Using-git-with-discipline.html][Drew Devault's /Tips for a disciplined git workflow/]]

D clog/how-i-learned-monads.md => clog/how-i-learned-monads.md +0 -78
@@ 1,78 0,0 @@
---
title: How I finally learned what a "monad" is
date: 2018-06-25
tldr: I struggled. But then I invented it to learn it.
---

I wrote Clojure, a functional programming language where monads are (implicitly)
everywhere, for 3+ years. I learned Haskell for 6+ months, enough time to put
together some trivial programs. I knew Common Lisp and Scheme, Python and Ruby.
I watched [videos][beckman] and read tutorials and [books][haskellbook]. I even
worked through most of SICP in [Shen][shen].

[shen]: https://shenlanguage.org
[beckman]: https://www.youtube.com/watch?v=ZhuHCtR3xq8
[haskellbook]: http://haskellbook.com/

Despite all of this, I still could not understand what a monad was or why it
would be useful. What finally made me understand monads was the frustration that
came from writing the same code over and over again in Elm.

Elm doesn't have the bind operator in its standard library (`>>=` in Haskell,
`some->` in Clojure). So you end up writing code like this all the time:

<label for="bind" class="margin-toggle">&#8853;</label><input type="checkbox"
id="bind" class="margin-toggle"/><span class="marginnote">The proper way to
solve this is to use the [`Maybe` module][elm-maybe] in the standard library, of
which I was unawares when I did this.</span> 

[elm-maybe]: http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Maybe

```elm
case comments of
   Nothing -> Nothing
   Just ls ->
       case List.first ls of
           Nothing -> div [] [ text "No comments" ]
           Just c ->
               div [ id "first-comment" ] [ text c ]
```

This is a contrived example but you get the idea. Lots of nested `case`
statements. I wrote a ton of this code until one day, reading the [Haskell
wikibook][hs-wikibook], it finally dawned on me that I could define my own bind
operator, just like the book says in that link, and clean up a lot of my Elm
code. So I did:

[hs-wikibook]: https://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe

```elm
(>>=) : Maybe a -> (a -> Maybe b) -> Maybe b
(>>=) m g =
    case m of
        Nothing ->
            Nothing

        Just x ->
            g x
```

And that was the day I finally *grokked* what a monad is. After using my Elm
version of `(>>=)` for a while, I began successfully using `(>>=)` in Haskell
code: I could write code using `(>>=)` and it would compile on the first try.

After implementing bind in Elm, I began to clearly see monads in my 
Haskell code before the compiler told me: I was becoming fluent in Haskell.

My point is that I only understood it after I *implemented it*. This reminds me
of a quote from _Difference and Repetition_ by Gilles Deleuze (p. 23):

> We learn nothing from those who say: 'Do as I do.' Our only teachers are those
> who tell us to 'do with me', and are able to emit signs to be developed in
> heterogeneity rather than to propose gestures for us to reproduce. In other
> words, there is no ideo-motivity, only sensory-motivity.

In related news, I've begun streaming some of my work in Haskell. If you would
like to 'code with me', you can join via chat at [bsima.me/live](/live) or you
can pair with me, just send me an email (ben@bsima.me) and we can discuss
logistics.

A clog/how-i-learned-monads.org => clog/how-i-learned-monads.org +66 -0
@@ 0,0 1,66 @@
#+title: How I finally learned what a "monad" is
#+date: 2018-06-25
#+subtitle: I struggled. But then I invented it to learn it.

I wrote Clojure, a functional programming language where monads are (implicitly)
everywhere, for 3+ years. I learned Haskell for 6+ months, enough time to put
together some trivial programs. I knew Common Lisp and Scheme, Python and
Ruby. I watched [[https://www.youtube.com/watch?v=ZhuHCtR3xq8][videos]] and read tutorials and [[http://haskellbook.com/][books]]. I even worked through most
of SICP in [[https://shenlanguage.org][Shen]].

Despite all of this, I still could not understand what a monad was or why it
would be useful. What finally made me understand monads was the frustration that
came from writing the same code over and over again in Elm.

Elm doesn't have the bind operator in its standard library (=>>== in Haskell,
=some->= in Clojure). So you end up writing code[fn:1] like this all the time:

[fn:1] The proper way to solve this is to use the [[http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Maybe][=Maybe= module]] in the standard
library, of which I was unawares when I did this.

#+BEGIN_EXAMPLE
case comments of
   Nothing -> Nothing
   Just ls ->
       case List.first ls of
           Nothing -> div [] [ text "No comments" ]
           Just c ->
               div [ id "first-comment" ] [ text c ]
#+END_EXAMPLE

This is a contrived example but you get the idea. Lots of nested =case=
statements. I wrote a ton of this code until one day, reading the [[https://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe][Haskell
wikibook]], it finally dawned on me that I could define my own bind operator, just
like the book says in that link, and clean up a lot of my Elm code. So I did:

#+BEGIN_EXAMPLE
(>>=) : Maybe a -> (a -> Maybe b) -> Maybe b
(>>=) m g =
    case m of
        Nothing ->
            Nothing

        Just x ->
            g x
#+END_EXAMPLE

And that was the day I finally /grokked/ what a monad is. After using my Elm
version of =(>>=)= for a while, I began successfully using =(>>=)= in Haskell
code: I could write code using =(>>=)= and it would compile on the first try.

After implementing bind in Elm, I began to clearly see monads in my Haskell code
before the compiler told me: I was becoming fluent in Haskell.

My point is that I only understood it after I /implemented it/. This reminds me
of a quote from /Difference and Repetition/ by Gilles Deleuze (p. 23):

#+BEGIN_QUOTE
We learn nothing from those who say: 'Do as I do.' Our only teachers are those
who tell us to 'do with me', and are able to emit signs to be developed in
heterogeneity rather than to propose gestures for us to reproduce. In other
words, there is no ideo-motivity, only sensory-motivity.
#+END_QUOTE

In related news, I've begun streaming some of my work in Haskell. If you would
like to 'code with me', you can join via chat at [[/live][bsima.me/live]] or you can pair
with me, just send me an email (ben@bsima.me) and we can discuss logistics.

D clog/learning-clojure.md => clog/learning-clojure.md +0 -61
@@ 1,61 0,0 @@
---
title: Clojure learning resources
date: January 7, 2014
---

[Clojure][clj] is a fascinating language and learning it has presented
an intellectual challenge I haven’t experienced in a long time. I
guess trying to wrap my head around all the various declensions and
forms in Attic Greek was the last thing that challenged me this much.

[clj]: https://clojure.org

As I’m learning Clojure, I’m finding all kinds of awesome resources
for learning, tools for building and testing, etc. Here’s what I’m
finding:

For most of the tools on here, if you follow the GitHub repos back to the user that owns the repo, they usually have other cool Clojure tools they build. Just a general observation about the Clojure community.

## Learnings

* [Clojure home](http://clojure.org) - There's a ton of good stuff here, like the rationale behind the design and explanations of the best features of Clojure.
* [Clojure.github.io](http://clojure.github.io/clojure/) - The core Clojure documentation. Useful for looking up functions and such.
* [Clojuredoc](http://clojure-doc.org/) - Community written Clojure documentation and articles
* [Clojure Koans](http://clojurekoans.com/) - Learn Clojure with Koans
  * When you get stuck, use [these YouTube videos](https://www.youtube.com/watch?v=P6S_1nCfjWA&list=PL1p6TgkbKXqyOwq6iSkce_EY5YWFHciHt) to help you.
* [4Clojure](http://www.4clojure.com/) - Solve simple problems to stretch your Clojure skills
* [CodeSchool](https://www.codeschool.com/code_tv/getting-started-with-clojure-part-1) - they have a couple screencasts on Clojure
* [Clojure 101](http://www.clojure101.com/) - Learn Clojure by making games
* [SICP in Clojure](http://sicpinclojure.com/) - The Structure and Interpretation of Computer Languages, in Clojure

## Frameworks and tools for making stuff

* [Speclj](http://speclj.com/) - A full-featured testing suit for Clojure. Pronounced "speckle".
* [Luminus](http://www.luminusweb.net/) - Web micro-framework
* [Pedestal](http://pedestal.io/) - Powerful webapp framework
* [Friend](https://github.com/cemerick/friend) - Authentication library for Clojure webapps. Yay.
* [Ring](https://github.com/ring-clojure/ring) - Webapp library and middleware
* [Clostache](https://github.com/fhd/clostache) - Mustache templating system for Clojure
* [C2](http://keminglabs.com/c2/) - Clojure(Script) Visualization
* [Korma](http://www.sqlkorma.com/) - Beautiful SQL for Clojure
* [Enlive](https://github.com/cgrand/enlive) - CSS selecting and screen scraping with Clojure


## Dev Tools

* [Serialize-fn](https://github.com/technomancy/serializable-fn) - Makes it easier to read function representations at the REPL
* [Vim-Fireplace](https://github.com/tpope/vim-fireplace) - For using the REPL from vim. Cool.
* [Leiningen](http://leiningen.org/) - For automating Clojure projects. *Always use this.*
* [Drake](https://github.com/Factual/drake) - Like "make" or "rake" but for data analytics/processing, built with Clojure
* [Cascalog](https://github.com/nathanmarz/cascalog) - a fully-featured data processing and querying library for Clojure or Java. Mainly for Hadoop.
* [Drip](https://github.com/flatland/drip) - Fast JVM launching! *Finally!*
* [Clojopts](https://github.com/amalloy/clojopts) - Run terminal commands from Clojure
* [Conch](https://github.com/Raynes/conch) - Also run terminal commands from Clojure
* [Cake](https://github.com/ninjudd/cake) - A build tool for Clojure. Kinda like an alternative to Leiningen, I think.
* [sdb](https://github.com/richhickey/sdb) - Clojure library for working with Amazon Simple DB
* [Marginalia](http://fogus.github.io/marginalia/) - Automattic documentation generator for your code.

## Stuff for Science

* [Incanter](http://incanter.org/) - R-like statistical computing in Clojure.
* [Clojuratica](http://clojuratica.weebly.com/) - Clojure + Mathematica = Orgasm

A clog/learning-clojure.org => clog/learning-clojure.org +79 -0
@@ 0,0 1,79 @@
#+title: Clojure learning resources
#+date: January 7, 2014

[[https://clojure.org][Clojure]] is a fascinating language and learning it has presented an intellectual
challenge I haven't experienced in a long time. I guess trying to wrap my head
around all the various declensions and forms in Attic Greek was the last thing
that challenged me this much.

As I'm learning Clojure, I'm finding all kinds of awesome resources for
learning, tools for building and testing, etc. Here's what I'm finding:

For most of the tools on here, if you follow the GitHub repos back to the user
that owns the repo, they usually have other cool Clojure tools they build. Just
a general observation about the Clojure community.

** Learnings
   :PROPERTIES:
   :CUSTOM_ID: learnings
   :ID:       42638bf0-c278-4fbe-814b-3d8ca29b9eb7
   :END:

- [[http://clojure.org][Clojure home]] - There's a ton of good stuff here, like the rationale behind the
  design and explanations of the best features of Clojure.
- [[http://clojure.github.io/clojure/][Clojure.github.io]] - The core Clojure documentation. Useful for looking up
  functions and such.
- [[http://clojure-doc.org/][Clojuredoc]] - Community written Clojure documentation and articles
- [[http://clojurekoans.com/][Clojure Koans]] - Learn Clojure with Koans
  - When you get stuck, use [[https://www.youtube.com/watch?v=P6S_1nCfjWA&list=PL1p6TgkbKXqyOwq6iSkce_EY5YWFHciHt][these YouTube videos]] to help you.
- [[http://www.4clojure.com/][4Clojure]] - Solve simple problems to stretch your Clojure skills
- [[https://www.codeschool.com/code_tv/getting-started-with-clojure-part-1][CodeSchool]] - they have a couple screencasts on Clojure
- [[http://www.clojure101.com/][Clojure 101]] - Learn Clojure by making games
- [[http://sicpinclojure.com/][SICP in Clojure]] - The Structure and Interpretation of Computer Languages, in
  Clojure

** Frameworks and tools for making stuff
   :PROPERTIES:
   :CUSTOM_ID: frameworks-and-tools-for-making-stuff
   :ID:       f69e2249-083a-44ec-9bf8-c602d2304a60
   :END:

- [[http://speclj.com/][Speclj]] - A full-featured testing suit for Clojure. Pronounced "speckle".
- [[http://www.luminusweb.net/][Luminus]] - Web micro-framework
- [[http://pedestal.io/][Pedestal]] - Powerful webapp framework
- [[https://github.com/cemerick/friend][Friend]] - Authentication library for Clojure webapps. Yay.
- [[https://github.com/ring-clojure/ring][Ring]] - Webapp library and middleware
- [[https://github.com/fhd/clostache][Clostache]] - Mustache templating system for Clojure
- [[http://keminglabs.com/c2/][C2]] - Clojure(Script) Visualization
- [[http://www.sqlkorma.com/][Korma]] - Beautiful SQL for Clojure
- [[https://github.com/cgrand/enlive][Enlive]] - CSS selecting and screen scraping with Clojure

** Dev Tools
   :PROPERTIES:
   :CUSTOM_ID: dev-tools
   :ID:       d342d9bf-3486-47a8-a83a-06c82ffe8eec
   :END:

- [[https://github.com/technomancy/serializable-fn][Serialize-fn]] - Makes it easier to read function representations at the REPL
- [[https://github.com/tpope/vim-fireplace][Vim-Fireplace]] - For using the REPL from vim. Cool.
- [[http://leiningen.org/][Leiningen]] - For automating Clojure projects. /Always use this./
- [[https://github.com/Factual/drake][Drake]] - Like "make" or "rake" but for data analytics/processing, built with
  Clojure
- [[https://github.com/nathanmarz/cascalog][Cascalog]] - a fully-featured data processing and querying library for Clojure
  or Java. Mainly for Hadoop.
- [[https://github.com/flatland/drip][Drip]] - Fast JVM launching!  /Finally!/
- [[https://github.com/amalloy/clojopts][Clojopts]] - Run terminal commands from Clojure
- [[https://github.com/Raynes/conch][Conch]] - Also run terminal commands from Clojure
- [[https://github.com/ninjudd/cake][Cake]] - A build tool for Clojure.  Kinda like an alternative to Leiningen, I
  think.
- [[https://github.com/richhickey/sdb][sdb]] - Clojure library for working with Amazon Simple DB
- [[http://fogus.github.io/marginalia/][Marginalia]] - Automattic documentation generator for your code.

** Stuff for Science
   :PROPERTIES:
   :CUSTOM_ID: stuff-for-science
   :ID:       a154084e-1b86-4539-b0e2-0e8f4d88a5cb
   :END:

- [[http://incanter.org/][Incanter]] - R-like statistical computing in Clojure.
- [[http://clojuratica.weebly.com/][Clojuratica]] - Clojure + Mathematica = Orgasm

D clog/perl-sunrise.md => clog/perl-sunrise.md +0 -62
@@ 1,62 0,0 @@
---
title: A Perl Script to Tell You The Sunrise and Sunset
date: May 2, 2017
tldr: That's right, I can still do Perl.
---

In college, I wanted to do bioinformatics research with [Dr Babbitt][babbitt]. I
pleaded to him and the dean of the medical school to allow a philosophy student
with no coding skills (at the time) to do this work. Babbitt said, take these
books on Perl, R, and statistics over the summer and talk to me in the fall. So
that's how I learned Perl. And R. Statistics came a bit later.

[babbitt]: https://www.rit.edu/science/people/gregory-babbitt

I don't actually dislike Perl, in fact I like it quite a bit. Nostalgia, no
doubt. Anyway, another thing I learned to like during college was waking up
around the same time as sunrise. It's definitely my greatest productivity hack.
I'm not saying this script will teach you to get up with the sun, but running
this in your systray, or as a cron job that sends you an SMS with tomorrow's
sunrise time, or even maybe even on a Raspberry Pi alarm clock, could
potentially help you get up earlier.

So here is the script, it's rather simple and self-explanatory I think. You
probably need to use CPAN to install the `DateTime::Event::Sunrise` package. And
don't forget to set the location variables.

```perl
#!/usr/bin/env perl

use strict;
use utf8;

use DateTime;
use DateTime::Event::Sunrise;


# Location
my $lat = "FIXME";
my $lon = "FIXME";


# Current date
my $now = DateTime->now;
$now->set_time_zone("local");

my $fmt = "%H:%M";

# Get sunrise and sunset data
my $sun = DateTime::Event::Sunrise->new (
    longitude => $lon,
    latitude  => $lat,
    precise   => 1
);

print "Sunrise: ", $sun->sunrise_datetime($now)->strftime($fmt);
print "\n";
print "Sunset: ", $sun->sunset_datetime($now)->strftime($fmt);
print "\n";
```

If you end up building that RPi alarm clock, do send me an email describing how
you did it. That sounds super cool.

A clog/perl-sunrise.org => clog/perl-sunrise.org +54 -0
@@ 0,0 1,54 @@
#+title: A Perl Script to Tell You The Sunrise and Sunset
#+date: May 2, 2017
#+subtitle: That's right, I can still do Perl.

In college, I wanted to do bioinformatics research with [[https://www.rit.edu/science/people/gregory-babbitt][Dr Babbitt]]. I pleaded to
him and the dean of the medical school to allow a philosophy student with no
coding skills (at the time) to do this work. Babbitt said, take these books on
Perl, R, and statistics over the summer and talk to me in the fall. So that's
how I learned Perl. And R. Statistics came a bit later.

I don't actually dislike Perl, in fact I like it quite a bit. Nostalgia, no
doubt. Anyway, another thing I learned to like during college was waking up
around the same time as sunrise. It's definitely my greatest productivity
hack. I'm not saying this script will teach you to get up with the sun, but
running this in your systray, or as a cron job that sends you an SMS with
tomorrow's sunrise time, or even maybe even on a Raspberry Pi alarm clock, could
potentially help you get up earlier.

So here is the script, it's rather simple and self-explanatory I think.  You
probably need to use CPAN to install the =DateTime::Event::Sunrise= package. And
don't forget to set the location variables.

#+BEGIN_SRC perl
  #!/usr/bin/env perl

  use strict; use utf8;

  use DateTime; use DateTime::Event::Sunrise;


  # Location
  my $lat = "FIXME";
  my $lon = "FIXME";


  # Current date
  my $now = DateTime->now;
  $now->set_time_zone("local");

  my $fmt = "%H:%M";

  # Get sunrise and sunset data
  my $sun = DateTime::Event::Sunrise->new (
      longitude => $lon,
      latitude  => $lat,
      precise   => 1
  );

  print "Sunrise: ", $sun->sunrise_datetime($now)->strftime($fmt); print "\n";
  print "Sunset: ", $sun->sunset_datetime($now)->strftime($fmt); print "\n";
#+END_SRC

If you end up building that RPi alarm clock, do send me an email describing how
you did it. That sounds super cool.

D clog/refactor-pattern-matching.md => clog/refactor-pattern-matching.md +0 -154
@@ 1,154 0,0 @@
---
title: Pattern matching as a tool for refactoring
date: March 31, 2017
tldr: Pattern matching is useful even if you don't end up using `match` because it helps you reason about your code
---


## A small example

Take the following snippet, slightly simplified from the original:

```clj
(defn reformat-req
  [{:keys [procid params] :as req}]
  (let [aq    (if (:id params) {:id (:id params)} {})
        query {:admin-data aq
               :tenant     (:tenant params)}
        q     {:type/procid   procid
               :type/time     (now)
               :type/tenant   (:tenant params)
               :type/user     (get-user req)
               :type/status   :processing
               :query/request query}]
    q))
```

Currently `query` looks like this:

```clj
;; when the :id key is in the params map
{:admin-data {:id id}
 :tenant     tenant}

;; when the :id key is NOT present
{:admin-data {}
 :tenant     tenant}
```

I need to refactor `query` to be like this:

```clj
{:type   :admin ; required
 :id     id     ; optional
 :tenant tenant ; optional
}
```

We know that the `params` map has _at least_ the `:tenant` key, and it
might have a `:id` key as well. Knowing this, we can identify 2
possible patterns that the data could be in:

1. Contains both `:tenant` and `:id`
2. Contains just `:tenant`

## Pattern Matching to the Rescue

A perfect solution for this is pattern matching

```clj
(match params
  ;; 1. Contains both `:tenant` and `:id`
  {:tenant t :id d} {:type :admin :tenant t :id d}
  ;; 2. Contains just `:tenant`
  {:tenant t} {:type :admin :tenant t}
  ;; 3. Fall thru in case neither is present
  _ {:type :admin})
```

The `match` function from [`core.match`][cm] first takes a map to
match on, in this case `params`. Then, it takes a series of patterns
and returns. In the first case, we want to match a map that has both
`:tenant` and `:id`, *and* we want to extract the values for each key
as `t` and `d` respectively. Then, we put that in a new map with
`:type :admin` and return the entire thing to the caller. The second
pattern, we only extract `:tenant`, and the third is a fail-safe in
case the caller forgot to add `:tenant` for whatever reason (according
to the spec, `:tenant` is technically optional). `_` in this case is a
wildcard.

[cm]: https://github.com/clojure/core.match/wiki/Basic-usage

**Nota bene:** we have to order our matches from most-specific to
least-specific. For example if we put the `{:tenant t}` pattern first,
then it could trigger a match *even though* there is a `:id` present.

## A Simpler Way

Now you might look at this and say, "it sure looks like you are
repeating yourself a lot." In which case you would be right, and there
is a simpler way to write this code:

```clj
(merge {:type :admin} (select-keys params [:id :tenant]))
```

This does the same thing as the pattern matching. `select-keys` will
take out `:id` and `:tenant` if they are present in `params`, and then
we merge those keys with `{:type :admin}`. We can't use `get` in this
case because, according to the spec, if the keys are in the final map,
then they must not be `nil`, and `get` will return `nil` if it doesn't
find the key in the `params` map.

However, it's very hard to see the succinct answer we came up with from
the first code snippet. In this case, going through the exercise of
pattern matching is valuable even though we didn't end up using
`match` because it made the structure of the data explicit. In the
original snippet, the data structure was there, but it was difficult
to see clearly in all the moving parts.

## The full refactor

At the end of the day, here is the full progression of refactoring:

```clj
;; original
(defn reformat-req
  [{:keys [procid params] :as req}]
  (let [aq    (if (:id params) {:id (:id params)} {})
        query {:admin-data aq
               :tenant     (:tenant params)}
        q     {:type/procid   procid
               :type/time     (now)
               :type/tenant   (:tenant params)
               :type/user     (get-user req)
               :type/status   :processing
               :query/request query}]
    q))

;; core.match version
(defn reformat-req
  [{:keys [procid params] :as req}]
  (let [query (match params
                {:tenant t :id d} {:type :admin :tenant t :id d}
                {:tenant t}       {:type :admin :tenant t}
                _                 {:type :admin})
        q     {:type/procid   procid
               :type/time     (now)
               :type/tenant   (:tenant params)
               :type/user     (get-user req)
               :type/status   :processing
               :query/request query}]
	q))
	
;; final, simplified
(defn reformat-req
  [{:keys [procid params] :as req}]
  (let [query (merge {:type :admin} (select-keys params [:id :tenant]))]
    {:type/procid   procid
     :type/time     (now)
     :type/tenant   (:tenant params)
     :type/user     (http-request->user req)
     :type/status   :processing
     :query/request query}))
```

A clog/refactor-pattern-matching.org => clog/refactor-pattern-matching.org +164 -0
@@ 0,0 1,164 @@
#+title: Pattern matching as a tool for refactoring
#+date: March 31, 2017
#+subtitle: Pattern matching is useful even if you don't end up using `match` because it helps you reason about your code


** A small example
   :PROPERTIES:
   :CUSTOM_ID: a-small-example
   :ID:       cde0f292-1ee0-4293-b233-b9e02a219046
   :END:

Take the following snippet, slightly simplified from the original:

#+BEGIN_EXAMPLE
    (defn reformat-req
      [{:keys [procid params] :as req}]
      (let [aq    (if (:id params) {:id (:id params)} {})
            query {:admin-data aq
                   :tenant     (:tenant params)}
            q     {:type/procid   procid
                   :type/time     (now)
                   :type/tenant   (:tenant params)
                   :type/user     (get-user req)
                   :type/status   :processing
                   :query/request query}]
        q))
#+END_EXAMPLE

Currently =query= looks like this:

#+BEGIN_EXAMPLE
    ;; when the :id key is in the params map
    {:admin-data {:id id}
     :tenant     tenant}

    ;; when the :id key is NOT present
    {:admin-data {}
     :tenant     tenant}
#+END_EXAMPLE

I need to refactor =query= to be like this:

#+BEGIN_EXAMPLE
    {:type   :admin ; required
     :id     id     ; optional
     :tenant tenant ; optional
    }
#+END_EXAMPLE

We know that the =params= map has /at least/ the =:tenant= key, and it might
have a =:id= key as well. Knowing this, we can identify 2 possible patterns that
the data could be in:

1. Contains both =:tenant= and =:id=
2. Contains just =:tenant=

** Pattern Matching to the Rescue
   :PROPERTIES:
   :CUSTOM_ID: pattern-matching-to-the-rescue
   :ID:       3f2971d9-10f9-4bfb-8396-36263a327ea8
   :END:

A perfect solution for this is pattern matching

#+BEGIN_EXAMPLE
    (match params
      ;; 1. Contains both `:tenant` and `:id`
      {:tenant t :id d} {:type :admin :tenant t :id d}
      ;; 2. Contains just `:tenant`
      {:tenant t} {:type :admin :tenant t}
      ;; 3. Fall thru in case neither is present
      _ {:type :admin})
#+END_EXAMPLE

The =match= function from
[[https://github.com/clojure/core.match/wiki/Basic-usage][=core.match=]] first
takes a map to match on, in this case =params=. Then, it takes a series of
patterns and returns. In the first case, we want to match a map that has both
=:tenant= and =:id=, /and/ we want to extract the values for each key as =t= and
=d= respectively. Then, we put that in a new map with =:type :admin= and return
the entire thing to the caller.  The second pattern, we only extract =:tenant=,
and the third is a fail-safe in case the caller forgot to add =:tenant= for
whatever reason (according to the spec, =:tenant= is technically optional). =_=
in this case is a wildcard.

*Nota bene:* we have to order our matches from most-specific to
least-specific. For example if we put the ={:tenant t}= pattern first, then it
could trigger a match /even though/ there is a =:id= present.

** A Simpler Way
   :PROPERTIES:
   :CUSTOM_ID: a-simpler-way
   :ID:       ac2c4f3f-47bc-47c9-9241-dc4820ae3b0c
   :END:

Now you might look at this and say, "it sure looks like you are repeating
yourself a lot." In which case you would be right, and there is a simpler way to
write this code:

#+BEGIN_EXAMPLE
    (merge {:type :admin} (select-keys params [:id :tenant]))
#+END_EXAMPLE

This does the same thing as the pattern matching. =select-keys= will take out
=:id= and =:tenant= if they are present in =params=, and then we merge those
keys with ={:type :admin}=. We can't use =get= in this case because, according
to the spec, if the keys are in the final map, then they must not be =nil=, and
=get= will return =nil= if it doesn't find the key in the =params= map.

However, it's very hard to see the succinct answer we came up with from the
first code snippet. In this case, going through the exercise of pattern matching
is valuable even though we didn't end up using =match= because it made the
structure of the data explicit. In the original snippet, the data structure was
there, but it was difficult to see clearly in all the moving parts.

** The full refactor
   :PROPERTIES:
   :CUSTOM_ID: the-full-refactor
   :ID:       22275bae-8759-468a-85af-008b27e8741e
   :END:

At the end of the day, here is the full progression of refactoring:

#+BEGIN_EXAMPLE
    ;; original
    (defn reformat-req
      [{:keys [procid params] :as req}]
      (let [aq    (if (:id params) {:id (:id params)} {})
            query {:admin-data aq
                   :tenant     (:tenant params)}
            q     {:type/procid   procid
                   :type/time     (now)
                   :type/tenant   (:tenant params)
                   :type/user     (get-user req)
                   :type/status   :processing
                   :query/request query}]
        q))

    ;; core.match version
    (defn reformat-req
      [{:keys [procid params] :as req}]
      (let [query (match params
                    {:tenant t :id d} {:type :admin :tenant t :id d}
                    {:tenant t}       {:type :admin :tenant t}
                    _                 {:type :admin})
            q     {:type/procid   procid
                   :type/time     (now)
                   :type/tenant   (:tenant params)
                   :type/user     (get-user req)
                   :type/status   :processing
                   :query/request query}]
        q))

    ;; final, simplified
    (defn reformat-req
      [{:keys [procid params] :as req}]
      (let [query (merge {:type :admin} (select-keys params [:id :tenant]))]
        {:type/procid   procid
         :type/time     (now)
         :type/tenant   (:tenant params)
         :type/user     (http-request->user req)
         :type/status   :processing
         :query/request query}))
#+END_EXAMPLE

D clog/robust-clojure-nil.md => clog/robust-clojure-nil.md +0 -349
@@ 1,349 0,0 @@
---
title: "Robust Clojure: The best way to handle nil"
date: April 17, 2017
tldr: Treat it as a type, like Nothing, not a value like null.
---

Large Clojure codebases can become nasty, just as in any other dynamic language.
Fortunately, Clojure isn't as problematic as some other languages because it is
partially inspired by ML. True, it doesn't have static typing, but the way
Clojure treats `nil` allows us to get very close to the ML way.

## Maybe

In Haskell and other ML-ish languages, the `Maybe` type represents either
`Nothing` or `Just <some_value>`. This becomes super useful when you need to
check if a thing exists and get the value of that thing at the same time.

For example doing this explicitly in Clojure is cumbersome:

```clj
(def data {:a 1 :b 2})

(if (= nil (:a data))
  0 ; default return value
  (:a data))
```

Checking for `nil` comes at a cost, of course. You're accessing the map twice,
and that's a lot of boilerplate code if you'll be doing this often. In Haskell
it's much cleaner:

```haskell
-- let's pretend this is a function that Maybe returns an Int
getSomeData :: Maybe Int

-- call the function and handle the return value
case getSomeData of
  Nothing -> Nothing
  Just a  -> a
```

We can handle both the *getting* of the value and the *returning* of the value
in one fell swoop.

Clojure has a function that does basically the same thing. The `get` function
will return `nil` if a key in a dictionary isn't present:

```clojure
(get {:a 1 :b 2} :a) ;=> 1
(get {:a 1 :b 2} :c) ;=> nil
```

This is similar to our imaginary `getSomeData` function in the Haskell snippet,
except the `Just a` is implicit, so we don't have to extract the value `1` every
time.

## Maybe `nil`?

Practically speaking, `nil` is a value in Clojure because you can do anything
with it that you can do with any other value. This idea of "everything is a
value" (commonly expressed as "everything is data") runs deep in the Lisp
tradition and gives Lisp languages a lot of power. But it also causes problems.
Consider:

```clojure
(+ 1 (get {:a 1 :b 2} :c))
```

This will evaluate to `(+ 1 nil)` which is nonsensical and will raise an error.
You can't increase nothing by `1`---if you try to, you just end up with more of
nothing!

## The Right Way

The simple fix is to check for `nil` just like you would check for `Nothing`.
Clojure provides the [`if-some`][ifsome] function to make this more concise:

[ifsome]: https://clojuredocs.org/clojure.core/if-some

```clojure
(if-some [it (get {:a 1 :b 2} :c)]
  (+ 1 it)
  nil)
```

Which is more-or-less the same in Haskell:

```haskell
case getSomeData of
  Nothing -> Nothing
  Just it -> 1 + it
```

If you remember to write all of your Clojure code like this, your codebase will
become much more robust to `nil`-related errors!

**To sum up: Always treat `nil` as if it means `Nothing`.**

If you're an intermediate Clojure programmer, then you're probably already
familiar with `if-let`/`if-some` and perhaps not impressed. The big idea,
however, is the treatment of `nil` as a type, and not as a value, which is a
subtle but important point.

To avoid these errors once and for all, you need to stop thinking about `nil` as
a *value*. Yes, that is how Clojure treats `nil`, but that doesn't mean that
you, the programmer, must treat it as a value too. If you come from Java or C,
which represents the absence of a value as the `null` value, then you'll have to
update your mental model.

**Realize:** the concept of absence refers to a *type of thing*, not a *value*.

While you are writing code, you should be thinking, "Is the type of this thing
*always* an `int`, or could it be `nil`?" When doing numerical or statistical
programming, you can probably guarantee that you'll have a number type returning
in your algorithms. However, when you start working with networking, or
databases, or certain Java libraries, you often lose the guarantee that
functions will return concrete values (network is down, database exploded,
etc.), and then you must think about `nil`.

## Clojure Idioms and Category Theory

In both Haskell and Clojure, manually checking for `nil`/`Nothing` becomes
tedious very fast, especially when you are chaining lots of functions together.
However both languages have solutions for this: Haskell has category theory,
Clojure has idioms.

In Haskell, the "bind" operator is defined basically like this:

```haskell
(>>=) m g = case m of
  Nothing -> Nothing  -- if m is Nothing, just return Nothing
  Just x  -> g x      -- otherwise, call the function g on the extracted value
```

Extending the above example, we can call `getSomeData` and increase it by `1`
with the following:

```haskell
incIfEven :: Int -> Maybe Int
incIfEven n =
  if n/2 == 0
  then Just n+1
  else Nothing

getSomeData >>= incIfEven
```

Clojure has a similar idiom. We use `some->>` to thread the map through the rest
of the functions. First extract a key if it exists, then lift the value into a
vector, so we can use all of the collection-related functions on it. This allows
us to `filter` and `map` over it to transform the data as we see fit:

```clojure
(some->> {:a 2 :b 3} :a vector (filter even?) (map inc) first) ;;=> 3
(some->> {:a 2 :b 3} :b vector (filter even?) (map inc) first) ;;=> nil
(some->> {:a 2 :b 3} :c vector (filter even?) (map inc) first) ;;=> nil
```

*Voilà!* You get the compactness of Haskell, without the overhead of category
theory :)

I kid! Category theory is great. The "bind" operator (`>>=`) is very similar to
`some->>` because they both take a value from one monad and "shove" it into the
next monad. <label for="monad" class="margin-toggle">&#8853;</label>
<input type="checkbox" id="monad" class="margin-toggle"/><span
class="marginnote">If you have no idea what a "monad" is, replace "monad" with
"thing" and re-read that sentence. </span>In Haskell, the monad is the `Maybe`
type; in Clojure, the monad is implicit in the collection interface which is the
unifying abstraction in the language.

## Clojure's Most Under-Appreciated Function

On IRC, [technomancy][] mentioned he was surprised `fnil` wasn't in this
article. I admit that completely forgot about `fnil`, but it's extremely useful.

[technomancy]: http://technomancy.us/

`fnil` can be used in our example above like so:

```clj
(def safe-inc (fnil inc 0))

(safe-inc (get {:a 1 :b 2} :b)) ;=> 3
(safe-inc (get {:a 1 :b 2} :c)) ;=> 1
```

In the above snippet, `safe-inc` is a function just like `(+ 1 x)` in the
earlier example, except if `x` is `nil`, then `safe-inc` will use `0` as a
default value instead. More (better) examples are available at [ClojureDocs][].

[ClojureDocs]: https://clojuredocs.org/clojure.core/fnil

`fnil` isn't talked about much in the Clojure community, but it is a handy
funciton. Use it whenever you aren't sure if a variable is `nil` but you do know
what the value *should* be. In fact, the entire problem of `nil` isn't discussed
much at all, but it is a very important issue, one that the Clojure community
should be aware of. Hopefully this article will at least make you aware of the
problems with `nil`, and start you down the path of thinking critically about
`nil` on your own.

## We Still Have Problems

The biggest problem is that this practice explicit `nil` handling is a
*convention*---the only thing enforcing it is your habits, and we all know that
we mere humans are fallible.  Haskell's approach to `Nothing` is thus superior
because the compiler checks your work automatically, which is nice.

A second problem is `nil` itself, which is a problem with any dynamically-typed
language. Unforeseen `nil`s can bubble up the stack and cause a lot of headache.
One solution is to use a monad library (discussed below), but more often than
not, in everyday Clojure code, a monad library is unnecessary.

The core problem is one of language design. Like I said above, Clojure treats
`nil` as a value, when in reality, the concept of absence refers to a *type*:
intuitively, we say "absence of a value" just like we say "an integer of 5".
Clojure, as a lisp, made the choice to keep types an evaluable construct, so
they could be modified at runtime, instead of a construct of compilation like
Haskell. By choosing Clojure over Haskell, you are choosing the power of
metaprogramming, but with that comes the drawbacks of dynamic typing.

The best solution to this that I've found (in dynamically-typed languages) is to
follow the single-responsibility principle: each function should just do `1`
thing. Then spec that function and catch the possible `nil`-causing inputs with
auto-generated tests (this is an article for another time). If you have other
solutions, please email me and I will add your contribution here :)

## Other Solutions and `nil`-Punning

As [described by Skyliner][skyliner], chaining `if-let`'s together like this is
annoying:

[skyliner]: https://blog.skyliner.io/fourteen-months-with-clojure-beb8b3e4bf00

```clj
(if-let [x (foo)]
  (if-let [y (bar x)]
    (if-let [z (goo x y)]
      (do (qux x y z)
          (log "it worked")
          true)
      (do (log "goo failed")
          false))
    (do (log "bar failed")
        false))
  (do (log "foo failed")
      false))
```

It's only mildly less annoying when using cats:

```clj
(require '[cats.core :as m])
(require '[cats.monad.either :as either])

@(m/mlet [x (if-let [v (foo)]
              (either/right v)
              (either/left))

          y (if-let [v (bar x)]
              (either/right v)
              (either/left))

          z (if-let [v (goo x y)]
              (either/right v)
              (either/left))]

  (m/return (qux x y z)))
```

The benefit with cats is you get fine-grained error handling for each `left`.
Read more about cats error handling and the [Either
type][either].

[either]: http://funcool.github.io/cats/latest/#either

If `some->` is out of the question, then personally I prefer the pattern
matching approach:

```clojure
(match (foo) ;; pretend `foo` is function that returns a map
  nil (log "foo failed")
  {:ms t :user u :data data} (do (log "User: " u " took " t " seconds.")
                                 data))
```

The benefit is mostly the same as with `if-let`, but you can pattern match on
the return value and then jump right into the next function, which I find myself
doing quite a lot.

Of course you can always tighten this up by defining your own version of "bind"
or `some->` in Clojure:

```clojure
(defn >>= [m g]
  (if-let [x (m)]
    (g x)
    (do (log (str (name m) " failed")
        nil))))
```

This is a (*very*) naïve implementation, but you get the idea. Modify to fit
your use-case.

On Reddit, tolitius [suggested][reddit] the use of `get`'s optional third
argument (which I had forgotten about!) and `or`:

> `get` has a default value built in:
>
> ```clj
> user=> (get {:a 1 :b 2} :b)
> 2
> user=> (get {:a 1 :b 2} :c 0)
> 0
> ```
>
> hence
>
> ```clj
> user=> (-> (get {:a 1 :b 2} :c 0) inc)
> 1
> ```
>
> In case this is a single op, such as `inc`, this would work as well:
>
> ```clj
> user=> (-> (or nil 41) inc)
> 42
>
> user=> (-> :c
>            {:a 1 :b 2}
>            (or 41)
>            inc)
> 42
> ```
>
> i.e. `or` is really handy for default values

[reddit]: https://www.reddit.com/r/Clojure/comments/65x15k/robust_clojure_the_best_way_to_handle_nil/dgenl5g/?utm_content=permalink&utm_medium=front&utm_source=reddit&utm_name=Clojure

Over at Lispcast, Eric Normand argues for the ["`nil`-punning"][pun] approach,
which is fine. But I think this approach requires a confused notion of what
`nil`/`Nothing` actually means. According to Eric, `nil` is a type, a value, a
key in a map, a boolean, an empty `seq`. It seems to me that "`nil`-punning" is
really just "`nil`-confusion". It is much simpler to understand `nil` as
`Nothing`, i.e. the absence of a value (which is a type). That said,
`nil`-punning in practice ends up mostly the same as I describe above, so either
technique will work.

[pun]: http://www.lispcast.com/nil-punning

A clog/robust-clojure-nil.org => clog/robust-clojure-nil.org +375 -0
@@ 0,0 1,375 @@
#+title: "Robust Clojure: The best way to handle nil"
#+date: April 17, 2017
#+tldr: Treat it as a type, like Nothing, not a value like null.

Large Clojure codebases can become nasty, just as in any other dynamic
language. Fortunately, Clojure isn't as problematic as some other
languages because it is partially inspired by ML. True, it doesn't have
static typing, but the way Clojure treats =nil= allows us to get very
close to the ML way.

** Maybe
   :PROPERTIES:
   :CUSTOM_ID: maybe
   :ID:       c58946b6-83a9-4b3e-9692-0288baac104e
   :END:

In Haskell and other ML-ish languages, the =Maybe= type represents
either =Nothing= or =Just <some_value>=. This becomes super useful when
you need to check if a thing exists and get the value of that thing at
the same time.

For example doing this explicitly in Clojure is cumbersome:

#+BEGIN_EXAMPLE
    (def data {:a 1 :b 2})

    (if (= nil (:a data))
      0 ; default return value
      (:a data))
#+END_EXAMPLE

Checking for =nil= comes at a cost, of course. You're accessing the map
twice, and that's a lot of boilerplate code if you'll be doing this
often. In Haskell it's much cleaner:

#+BEGIN_SRC haskell
    -- let's pretend this is a function that Maybe returns an Int
    getSomeData :: Maybe Int

    -- call the function and handle the return value
    case getSomeData of
      Nothing -> Nothing
      Just a  -> a
#+END_SRC

We can handle both the /getting/ of the value and the /returning/ of the
value in one fell swoop.

Clojure has a function that does basically the same thing. The =get=
function will return =nil= if a key in a dictionary isn't present:

#+BEGIN_SRC clojure
    (get {:a 1 :b 2} :a) ;=> 1
    (get {:a 1 :b 2} :c) ;=> nil
#+END_SRC

This is similar to our imaginary =getSomeData= function in the Haskell
snippet, except the =Just a= is implicit, so we don't have to extract
the value =1= every time.

** Maybe =nil=?
   :PROPERTIES:
   :CUSTOM_ID: maybe-nil
   :ID:       53d725f6-361e-4584-b6a1-b8823d51f130
   :END:

Practically speaking, =nil= is a value in Clojure because you can do
anything with it that you can do with any other value. This idea of
"everything is a value" (commonly expressed as "everything is data")
runs deep in the Lisp tradition and gives Lisp languages a lot of power.
But it also causes problems. Consider:

#+BEGIN_SRC clojure
    (+ 1 (get {:a 1 :b 2} :c))
#+END_SRC

This will evaluate to =(+ 1 nil)= which is nonsensical and will raise an
error. You can't increase nothing by =1=---if you try to, you just end
up with more of nothing!

** The Right Way
   :PROPERTIES:
   :CUSTOM_ID: the-right-way
   :ID:       2f2b6a3a-7b41-4519-8e0f-aa1afd22d4aa
   :END:

The simple fix is to check for =nil= just like you would check for
=Nothing=. Clojure provides the
[[https://clojuredocs.org/clojure.core/if-some][=if-some=]] function to
make this more concise:

#+BEGIN_SRC clojure
    (if-some [it (get {:a 1 :b 2} :c)]
      (+ 1 it)
      nil)
#+END_SRC

Which is more-or-less the same in Haskell:

#+BEGIN_SRC haskell
    case getSomeData of
      Nothing -> Nothing
      Just it -> 1 + it
#+END_SRC

If you remember to write all of your Clojure code like this, your
codebase will become much more robust to =nil=-related errors!

*To sum up: Always treat =nil= as if it means =Nothing=.*

If you're an intermediate Clojure programmer, then you're probably
already familiar with =if-let=/=if-some= and perhaps not impressed. The
big idea, however, is the treatment of =nil= as a type, and not as a
value, which is a subtle but important point.

To avoid these errors once and for all, you need to stop thinking about
=nil= as a /value/. Yes, that is how Clojure treats =nil=, but that
doesn't mean that you, the programmer, must treat it as a value too. If
you come from Java or C, which represents the absence of a value as the
=null= value, then you'll have to update your mental model.

*Realize:* the concept of absence refers to a /type of thing/, not a
/value/.

While you are writing code, you should be thinking, "Is the type of this
thing /always/ an =int=, or could it be =nil=?" When doing numerical or
statistical programming, you can probably guarantee that you'll have a
number type returning in your algorithms. However, when you start
working with networking, or databases, or certain Java libraries, you
often lose the guarantee that functions will return concrete values
(network is down, database exploded, etc.), and then you must think
about =nil=.

** Clojure Idioms and Category Theory
   :PROPERTIES:
   :CUSTOM_ID: clojure-idioms-and-category-theory
   :ID:       27259dc1-181b-4715-ab16-c749ca4acea5
   :END:

In both Haskell and Clojure, manually checking for =nil=/=Nothing=
becomes tedious very fast, especially when you are chaining lots of
functions together. However both languages have solutions for this:
Haskell has category theory, Clojure has idioms.

In Haskell, the "bind" operator is defined basically like this:

#+BEGIN_SRC haskell
    (>>=) m g = case m of
      Nothing -> Nothing  -- if m is Nothing, just return Nothing
      Just x  -> g x      -- otherwise, call the function g on the extracted value
#+END_SRC

Extending the above example, we can call =getSomeData= and increase it
by =1= with the following:

#+BEGIN_SRC haskell
    incIfEven :: Int -> Maybe Int
    incIfEven n =
      if n/2 == 0
      then Just n+1
      else Nothing

    getSomeData >>= incIfEven
#+END_SRC

Clojure has a similar idiom. We use =some->>= to thread the map through
the rest of the functions. First extract a key if it exists, then lift
the value into a vector, so we can use all of the collection-related
functions on it. This allows us to =filter= and =map= over it to
transform the data as we see fit:

#+BEGIN_SRC clojure
    (some->> {:a 2 :b 3} :a vector (filter even?) (map inc) first) ;;=> 3
    (some->> {:a 2 :b 3} :b vector (filter even?) (map inc) first) ;;=> nil
    (some->> {:a 2 :b 3} :c vector (filter even?) (map inc) first) ;;=> nil
#+END_SRC

/Voilà!/ You get the compactness of Haskell, without the overhead of
category theory :)

I kid! Category theory is great. The "bind" operator (=>>==) is very
similar to =some->>= because they both take a value from one monad and
"shove" it into the next monad. ⊕ If you have no idea what a "monad" is,
replace "monad" with "thing" and re-read that sentence. In Haskell, the
monad is the =Maybe= type; in Clojure, the monad is implicit in the
collection interface which is the unifying abstraction in the language.

** Clojure's Most Under-Appreciated Function
   :PROPERTIES:
   :CUSTOM_ID: clojures-most-under-appreciated-function
   :ID:       15cc2567-6994-483a-80af-f7203e413431
   :END:

On IRC, [[http://technomancy.us/][technomancy]] mentioned he was
surprised =fnil= wasn't in this article. I admit that completely forgot
about =fnil=, but it's extremely useful.

=fnil= can be used in our example above like so:

#+BEGIN_EXAMPLE
    (def safe-inc (fnil inc 0))

    (safe-inc (get {:a 1 :b 2} :b)) ;=> 3
    (safe-inc (get {:a 1 :b 2} :c)) ;=> 1
#+END_EXAMPLE

In the above snippet, =safe-inc= is a function just like =(+ 1 x)= in
the earlier example, except if =x= is =nil=, then =safe-inc= will use
=0= as a default value instead. More (better) examples are available at
[[https://clojuredocs.org/clojure.core/fnil][ClojureDocs]].

=fnil= isn't talked about much in the Clojure community, but it is a
handy funciton. Use it whenever you aren't sure if a variable is =nil=
but you do know what the value /should/ be. In fact, the entire problem
of =nil= isn't discussed much at all, but it is a very important issue,
one that the Clojure community should be aware of. Hopefully this
article will at least make you aware of the problems with =nil=, and
start you down the path of thinking critically about =nil= on your own.

** We Still Have Problems
   :PROPERTIES:
   :CUSTOM_ID: we-still-have-problems
   :ID:       2df90330-1699-4c0e-889f-f8415077bdd1
   :END:

The biggest problem is that this practice explicit =nil= handling is a
/convention/---the only thing enforcing it is your habits, and we all
know that we mere humans are fallible. Haskell's approach to =Nothing=
is thus superior because the compiler checks your work automatically,
which is nice.

A second problem is =nil= itself, which is a problem with any
dynamically-typed language. Unforeseen =nil=s can bubble up the stack
and cause a lot of headache. One solution is to use a monad library
(discussed below), but more often than not, in everyday Clojure code, a
monad library is unnecessary.

The core problem is one of language design. Like I said above, Clojure
treats =nil= as a value, when in reality, the concept of absence refers
to a /type/: intuitively, we say "absence of a value" just like we say
"an integer of 5". Clojure, as a lisp, made the choice to keep types an
evaluable construct, so they could be modified at runtime, instead of a
construct of compilation like Haskell. By choosing Clojure over Haskell,
you are choosing the power of metaprogramming, but with that comes the
drawbacks of dynamic typing.

The best solution to this that I've found (in dynamically-typed
languages) is to follow the single-responsibility principle: each
function should just do =1= thing. Then spec that function and catch the
possible =nil=-causing inputs with auto-generated tests (this is an
article for another time). If you have other solutions, please email me
and I will add your contribution here :)

** Other Solutions and =nil=-Punning
   :PROPERTIES:
   :CUSTOM_ID: other-solutions-and-nil-punning
   :ID:       3c72fa62-cb45-471c-a618-7c7fa3d7f7a6
   :END:

As
[[https://blog.skyliner.io/fourteen-months-with-clojure-beb8b3e4bf00][described
by Skyliner]], chaining =if-let='s together like this is annoying:

#+BEGIN_EXAMPLE
    (if-let [x (foo)]
      (if-let [y (bar x)]
        (if-let [z (goo x y)]
          (do (qux x y z)
              (log "it worked")
              true)
          (do (log "goo failed")
              false))
        (do (log "bar failed")
            false))
      (do (log "foo failed")
          false))
#+END_EXAMPLE

It's only mildly less annoying when using cats:

#+BEGIN_EXAMPLE
    (require '[cats.core :as m])
    (require '[cats.monad.either :as either])

    @(m/mlet [x (if-let [v (foo)]
                  (either/right v)
                  (either/left))

              y (if-let [v (bar x)]
                  (either/right v)
                  (either/left))

              z (if-let [v (goo x y)]
                  (either/right v)
                  (either/left))]

      (m/return (qux x y z)))
#+END_EXAMPLE

The benefit with cats is you get fine-grained error handling for each
=left=. Read more about cats error handling and the
[[http://funcool.github.io/cats/latest/#either][Either type]].

If =some->= is out of the question, then personally I prefer the pattern
matching approach:

#+BEGIN_SRC clojure
    (match (foo) ;; pretend `foo` is function that returns a map
      nil (log "foo failed")
      {:ms t :user u :data data} (do (log "User: " u " took " t " seconds.")
                                     data))
#+END_SRC

The benefit is mostly the same as with =if-let=, but you can pattern
match on the return value and then jump right into the next function,
which I find myself doing quite a lot.

Of course you can always tighten this up by defining your own version of
"bind" or =some->= in Clojure:

#+BEGIN_SRC clojure
  (defn >>= [m g]
    (if-let [x (m)]
      (g x)
      (do (log (str (name m) " failed")
               nil))))
#+END_SRC

This is a (/very/) naïve implementation, but you get the idea. Modify to fit
your use-case.

On Reddit, tolitius [[https://www.reddit.com/r/Clojure/comments/65x15k/robust_clojure_the_best_way_to_handle_nil/dgenl5g/?utm_content=permalink&utm_medium=front&utm_source=reddit&utm_name=Clojure][suggested]] the use of =get='s optional third argument (which
I had forgotten about!) and =or=:

#+BEGIN_QUOTE
  =get= has a default value built in:

  #+BEGIN_EXAMPLE
      user=> (get {:a 1 :b 2} :b)
      2
      user=> (get {:a 1 :b 2} :c 0)
      0
  #+END_EXAMPLE

  hence

  #+BEGIN_EXAMPLE
      user=> (-> (get {:a 1 :b 2} :c 0) inc)
      1
  #+END_EXAMPLE

  In case this is a single op, such as =inc=, this would work as well:

  #+BEGIN_EXAMPLE
      user=> (-> (or nil 41) inc)
      42

      user=> (-> :c
                 {:a 1 :b 2}
                 (or 41)
                 inc)
      42
  #+END_EXAMPLE

  i.e. =or= is really handy for default values
#+END_QUOTE

Over at Lispcast, Eric Normand argues for the [[http://www.lispcast.com/nil-punning]["=nil=-punning"]] approach, which is
fine. But I think this approach requires a confused notion of what
=nil=/=Nothing= actually means. According to Eric, =nil= is a type, a value, a
key in a map, a boolean, an empty =seq=. It seems to me that "=nil=-punning" is
really just "=nil=-confusion". It is much simpler to understand =nil= as
=Nothing=, i.e. the absence of a value (which is a type). That said,
=nil=-punning in practice ends up mostly the same as I describe above, so either
technique will work.

D clog/server-tools.md => clog/server-tools.md +0 -87
@@ 1,87 0,0 @@
---
title: 3 Tools I Use On Every Server
date: May 16, 2017 
tldr: The first things I install when I start a fun new adventure.
---

I've setup more servers than I care to remember. Each time I setup a server, I
always go through the same steps of configuring ssh, opening and closing ports,
setting up a firewall, and so on. Despite the advancements in DevOps over the
past few years, I've come to the conclusion that these steps are unavoidable,
the best thing to do is make my stay on the server a bit more enjoyable.

This isn't too hard, assuming a decent familiarity with the command line. These
are the three tools I use on every server to make my ride more comfortable, and
hopefully they'll make your ride a bit more comfortable too.

## Mosh

"Mosh" stands for the "mobile shell", but it might as well stand for "magical
shell" because it is really rather extraordinary. Mosh will use ssh to
authenticate you into the server, but then it uses it's own protocol to keep the
session alive _even if you drop the connection_.

I have literally moshed into a server in one airport, flown across the country,
and then resumed the session in another airport. This is especially great for
remote workers such as myself that tend to hop between coffee shops and would
like to pick up where they left off at the last café.

Plus, saying you're _moshed into the server_ is way cooler than saying you are
_es es aiched in_. 

Seriously, mosh is wonderful. [Learn how to install and configure mosh
here][mosh].

## Tmux

If you regularly have multiple terminals open while working, but you've never
tried tmux, then this is your wake up call. Give it a few hours of your time,
learn the basics, and you won't regret it.

Simply put, tmux ("terminal multiplexer") allows you to run _multiple terminals_
inside a _single terminal_.

My tmux use-case is very simple. On my home server I have a tmux session always
running. I mosh in to the server, then do `tmux attach` and I can join the tmux
session where I left off. I usually have 4-5 windows open in tmux for running
tests on my work code, managing a few support services (e.g. an ELK stack) for
said work code, mucking around in directories, and so on. 

With the combination of mosh and tmux, I can be moshed into my home server,
start running the test suite while at my home office, close my laptop and bike
to the coffee shop, then open up and read the test results without without
skipping a beat. This works perfectly because the time it takes to bike to
coffee is about the same time it takes to compile and test all the code! (Ha!)

There are many guides online for installing, configuring, and using tmux, so
I'll leave it to you to find one you like. Personally, I'm always forgetting
tmux shortcuts, so the [DuckDuckGo cheat sheet][ddg] comes in handy quite often.
I also think [this tmux config][.tmux] is a nice starting point.

## Htop

I can never remember how to read all the stuff that [top][] gives me, but in
htop the information is organized and presented so well as to be obvious. Htop
is simply a better top.


It's a small program and is available in every package manager that I've had the
pleasure to use; installing htop is usually the first thing I do when I'm on a
new server. `sudo apt install htop` Boom. Done. Learn more at the [official htop
homepage][htop]

## Bonus!

I would be remiss if I didn't mention [ranger][ranger]. Although it's pretty
well-known by now, and it's not a necessity, it made this list because it is
certainly a nice-to-have.

If you have more awesome tools to share, send me an email at ben@bsima.me, I
would love to learn what you have to teach.

[mosh]: https://mosh.org
[ddg]: https://duckduckgo.com/?q=tmux+cheat+sheet&t=ffab&atb=v35-2&ia=answer
[.tmux]: https://github.com/gpakosz/.tmux
[top]: https://en.wikipedia.org/wiki/Top_(software)
[htop]: http://hisham.hm/htop/
[ranger]: http://ranger.nongnu.org/ 

A clog/server-tools.org => clog/server-tools.org +92 -0
@@ 0,0 1,92 @@
#+title: 3 Tools I Use On Every Server
#+date: May 16, 2017
#+subtitle: The first things I install when I start a fun new adventure.

I've setup more servers than I care to remember. Each time I setup a server, I
always go through the same steps of configuring ssh, opening and closing ports,
setting up a firewall, and so on. Despite the advancements in DevOps over the
past few years, I've come to the conclusion that these steps are unavoidable,
the best thing to do is make my stay on the server a bit more enjoyable.

This isn't too hard, assuming a decent familiarity with the command line. These
are the three tools I use on every server to make my ride more comfortable, and
hopefully they'll make your ride a bit more comfortable too.

** Mosh
   :PROPERTIES:
   :CUSTOM_ID: mosh
   :ID:       da237676-15ac-469c-baef-36a0257c82f1
   :END:

"Mosh" stands for the "mobile shell", but it might as well stand for "magical
shell" because it is really rather extraordinary. Mosh will use ssh to
authenticate you into the server, but then it uses it's own protocol to keep the
session alive /even if you drop the connection/.

I have literally moshed into a server in one airport, flown across the country,
and then resumed the session in another airport. This is especially great for
remote workers such as myself that tend to hop between coffee shops and would
like to pick up where they left off at the last café.

Plus, saying you're /moshed into the server/ is way cooler than saying you are
/es es aiched in/.

Seriously, mosh is wonderful. [[https://mosh.org][Learn how to install and configure mosh here]].

** Tmux
   :PROPERTIES:
   :CUSTOM_ID: tmux
   :ID:       ca226457-32bf-4ad6-adb8-4a3c6de7dac1
   :END:

If you regularly have multiple terminals open while working, but you've never
tried tmux, then this is your wake up call. Give it a few hours of your time,
learn the basics, and you won't regret it.

Simply put, tmux ("terminal multiplexer") allows you to run /multiple terminals/
inside a /single terminal/.

My tmux use-case is very simple. On my home server I have a tmux session always
running. I mosh in to the server, then do =tmux attach= and I can join the tmux
session where I left off. I usually have 4-5 windows open in tmux for running
tests on my work code, managing a few support services (e.g. an ELK stack) for
said work code, mucking around in directories, and so on.

With the combination of mosh and tmux, I can be moshed into my home server,
start running the test suite while at my home office, close my laptop and bike
to the coffee shop, then open up and read the test results without without
skipping a beat. This works perfectly because the time it takes to bike to
coffee is about the same time it takes to compile and test all the code! (Ha!)

There are many guides online for installing, configuring, and using tmux, so
I'll leave it to you to find one you like. Personally, I'm always forgetting
tmux shortcuts, so the [[https://duckduckgo.com/?q=tmux+cheat+sheet&t=ffab&atb=v35-2&ia=answer][DuckDuckGo cheat sheet]] comes in handy quite often. I also
think [[https://github.com/gpakosz/.tmux][this tmux config]] is a nice starting point.

** Htop
   :PROPERTIES:
   :CUSTOM_ID: htop
   :ID:       87dcf703-aac1-420c-9557-dddde0887a4f
   :END:

I can never remember how to read all the stuff that [[https://en.wikipedia.org/wiki/Top_(software)][top]] gives me, but in htop
the information is organized and presented so well as to be obvious. Htop is
simply a better top.

It's a small program and is available in every package manager that I've had the
pleasure to use; installing htop is usually the first thing I do when I'm on a
new server. =sudo apt install htop= Boom. Done. Learn more at the [[http://hisham.hm/htop/][official htop
homepage]]

** Bonus!
   :PROPERTIES:
   :CUSTOM_ID: bonus
   :ID:       762a5a26-2e0c-4939-959c-ae4f9c2c5844
   :END:

I would be remiss if I didn't mention [[http://ranger.nongnu.org/][ranger]]. Although it's pretty well-known by
now, and it's not a necessity, it made this list because it is certainly a
nice-to-have.

If you have more awesome tools to share, send me an email at ben@bsima.me, I
would love to learn what you have to teach.

D clog/sql-yesod-persistent.md => clog/sql-yesod-persistent.md +0 -268
@@ 1,268 0,0 @@
---
title: SQL Database Design with Yesod and Persistent
date: 2018-06-24
tldr: How to write your models for a normalized database.
---

If you've ever designed a database from scratch, or worked with a database
migrations, then you know how important it is to get the data schema right the
first time. If you get them *wrong*, then when you (inevitably) have to fix it,
you must do a major overhaul of your code just to fit the updated schema. In
Rails, this means re-implementing potentially dozens of objects. In Haskell,
it's not as bad because the compiler handles most error checking (with
[Persistent](https://github.com/yesodweb/persistent), anyhow), but it's still
not a trivial exercise.

So how do you design a database with Persistent? You begin with *database
normalization* (DN) in mind. The objectives of DN are to minimize the amount
of redesign you have to do later, reduce data redundancy, and reduce data
anomalies (double insertions, old data, records don't get deleted, etc):

> 1. To free the collection of relations from undesirable insertion, update and
>    deletion dependencies;
> 2. To reduce the need for restructuring the collection of relations, as new
>    types of data are introduced, and thus increase the life span of
>    application programs;
> 3. To make the relational model more informative to users;
> 4. To make the collection of relations neutral to the query statistics, where
>    these statistics are liable to change as time goes by.
> 
> E.F. Codd, "Further Normalization of the Data Base Relational Model"

In toto, database
normalization means to simplify the design of the database. Let's see what that
means mathematically, and then work through an example in Haskell.

## Definitions

(all from Wikipedia) 

### Non-Prime Attributes

In order to understand the normal forms, we first need to understand non-prime
attributes. 

> A *non-prime attribute* of a relation R is an attribute that does not
> belong to any candidate key of R

Okay, so it's a column in the table that *is not part of a candidate key*. So,
what's a candidate key?

> A candidate key of a relation is a minimal superkey for that relation; that
> is, a set of attributes such that: 
> 
> 1. the relation does not have two distinct tuples (i.e. rows or records in
>    common database language) with the same values for these attributes (which
>    means that the set of attributes is a superkey) 
> 2. there is no proper subset of these attributes for which (1) holds (which
>    means that the set is minimal).

### First Normal Form (1NF)

> A relation is in first normal form if and only if the domain of each
> attribute contains only atomic (indivisible) values, and the value of
> each attribute contains only a single value from that domain.
> (Wikipedia)

So basically, 1NF means each column in the database is as *small* as
we can make it. By "small" I mean simple, atomic, indivisible. This is
intentionally vague and does not have a concrete definition. As the
database *designer*, one of your design decisions includes determining
what that atomic parts of the schema should be.

### Second Normal Form (2NF)

So, the Wikipedia definition is rather dense:

> a relation is in 2NF if it is in 1NF and no non-prime attribute is
> dependent on any proper subset of any candidate key of the relation.
> **A non-prime attribute of a relation** is an attribute that is not a
> part of any candidate key of the relation.

As far as I can tell, 2NF is about removing duplication by minimizing
the number of possible primary keys in the row. There is a rigorous,
mathematical definition for this, but I'm not going that rabbit hole
today.

### Third Normal Form (3NF)

3NF has 2 requirements:

  - The table/relation (R) must be in 2NF
  - Every non-prime attribute of R is non-transitively dependent on
    every key of R.

## An Example

Lets say I have the following "Customers" table in my database (also
from Wikipedia):

<table>
<thead>
<tr class="header">
<th>Customer ID</th>
<th>First Name</th>
<th>Surname</th>
<th>Telephone Number</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>123</td>
<td>Pooja</td>
<td>Singh</td>
<td>555-861-2025, 192-122-1111</td>
</tr>
<tr class="even">
<td>456</td>
<td>San</td>
<td>Zhang</td>
<td>(555) 403-1659 Ext. 53; 182-929-2929</td>
</tr>
<tr class="odd">
<td>789</td>
<td>John</td>
<td>Doe</td>
<td>555-808-9633</td>
</tr>
</tbody>
</table>

This can be described with the following Persistent entity:

    Customers
        firstname Text
        surname Text
        telephoneNumber Text

You'll notice this is definitely not *normal*. The telephone column
does not have a format to which all phone numbers conform, therefore
there is no norm. Imagine writing a decoder for the telephone column: it
would be difficult and annoying. We need to normalize this data to make
life easier.

## One-to-Many

The simplest and most flexible solution is to break up the telephone
column into its own table:

<table>
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><table>
<caption>Customer Name</caption>
<thead>
<tr class="header">
<th>Customer ID</th>
<th>First Name</th>
<th>Surname</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>123</td>
<td>Pooja</td>
<td>Singh</td>
</tr>
<tr class="even">
<td>456</td>
<td>San</td>
<td>Zhang</td>
</tr>
<tr class="odd">
<td>789</td>
<td>John</td>
<td>Doe</td>
</tr>
</tbody>
</table></td>
<td><table>
<caption>Customer Telephone Number</caption>
<thead>
<tr class="header">
<th>Customer ID</th>
<th>Telephone Number</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>123</td>
<td>555-861-2025</td>
</tr>
<tr class="even">
<td>123</td>
<td>192-122-1111</td>
</tr>
<tr class="odd">
<td>456</td>
<td>(555) 403-1659 Ext. 53</td>
</tr>
<tr class="even">
<td>456</td>
<td>182-929-2929</td>
</tr>
<tr class="odd">
<td>789</td>
<td>555-808-9633</td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>

This establishes a one-to-many relationship between customers and
telephone numbers: as you can see, the `Customer Id` field has `456`
listed twice, . In Persistent this would look like:

    Customer
        firstname Text
        surname Text
    
    CustomerTelephone
        customer CustomerId
        telephoneNumber Text

`CustomerId` is a foreign key linking the customer's telephone number
to the customer's name.

## Many-to-Many

Breaking up your columns into tables like this also allows for arbitrary
extension. What if, later on, you decide you need addresses for each of
your customers? Doing so is as easy as:

    Address
       street Text
       city Text
       country Text
       zipcode Text
    
    CustomerAddress
        customer CustomerId
        address AddressId
        UniqCustomerAddress customer address

`CustomerAddress` is a join table that establishes a many-to-many
relationship; each customer can be linked to multiple addresses, and
vice versa.  

## References, etc.

  - [Yesod Book, Persistent
    Chapter](https://www.yesodweb.com/book/persistent)
  - [Persistent
    Wiki](https://github.com/yesodweb/persistent/tree/master/docs#wiki)
  - [Persistent Entity
    Syntax](https://github.com/yesodweb/persistent/blob/master/docs/Persistent-entity-syntax.md)
  - Wikipedia
      - [Database
        normalization](https://en.wikipedia.org/w/index.php?title=Database_normalization&oldid=818370313)
      - First normal form
      - Second normal form
      - Third normal form


A clog/sql-yesod-persistent.org => clog/sql-yesod-persistent.org +882 -0
@@ 0,0 1,882 @@
#+title: SQL Database Design with Yesod and Persistent
#+date: 2018-06-24
#+subtitle: How to write your models for a normalized database.

If you've ever designed a database from scratch, or worked with a
database migrations, then you know how important it is to get the data
schema right the first time. If you get them /wrong/, then when you
(inevitably) have to fix it, you must do a major overhaul of your code
just to fit the updated schema. In Rails, this means re-implementing
potentially dozens of objects. In Haskell, it's not as bad because the
compiler handles most error checking (with
[[https://github.com/yesodweb/persistent][Persistent]], anyhow), but
it's still not a trivial exercise.

So how do you design a database with Persistent? You begin with
/database normalization/ (DN) in mind. The objectives of DN are to
minimize the amount of redesign you have to do later, reduce data
redundancy, and reduce data anomalies (double insertions, old data,
records don't get deleted, etc):

#+BEGIN_QUOTE

  1. To free the collection of relations from undesirable insertion,
     update and deletion dependencies;
  2. To reduce the need for restructuring the collection of relations,
     as new types of data are introduced, and thus increase the life
     span of application programs;
  3. To make the relational model more informative to users;
  4. To make the collection of relations neutral to the query
     statistics, where these statistics are liable to change as time
     goes by.

  E.F. Codd, "Further Normalization of the Data Base Relational Model"
#+END_QUOTE

In toto, database normalization means to simplify the design of the
database. Let's see what that means mathematically, and then work
through an example in Haskell.

** Definitions
   :PROPERTIES:
   :CUSTOM_ID: definitions
   :ID:       05bab4a4-7a7c-40e7-9af8-58b79e774fac
   :END:

(all from Wikipedia)

*** Non-Prime Attributes
    :PROPERTIES:
    :CUSTOM_ID: non-prime-attributes
    :ID:       442c5d49-8e62-4762-b1a2-8493f522a92f
    :END:

In order to understand the normal forms, we first need to understand
non-prime attributes.

#+BEGIN_QUOTE
  A /non-prime attribute/ of a relation R is an attribute that does not
  belong to any candidate key of R
#+END_QUOTE

Okay, so it's a column in the table that /is not part of a candidate
key/. So, what's a candidate key?

#+BEGIN_QUOTE
  A candidate key of a relation is a minimal superkey for that relation;
  that is, a set of attributes such that:

  1. the relation does not have two distinct tuples (i.e. rows or
     records in common database language) with the same values for these
     attributes (which means that the set of attributes is a superkey)
  2. there is no proper subset of these attributes for which (1) holds
     (which means that the set is minimal).
#+END_QUOTE

*** First Normal Form (1NF)
    :PROPERTIES:
    :CUSTOM_ID: first-normal-form-1nf
    :ID:       4153c472-b54f-4699-b9a5-5b3e8def881e
    :END:

#+BEGIN_QUOTE
  A relation is in first normal form if and only if the domain of each
  attribute contains only atomic (indivisible) values, and the value of
  each attribute contains only a single value from that domain.
  (Wikipedia)
#+END_QUOTE

So basically, 1NF means each column in the database is as /small/ as we
can make it. By "small" I mean simple, atomic, indivisible. This is
intentionally vague and does not have a concrete definition. As the
database /designer/, one of your design decisions includes determining
what that atomic parts of the schema should be.

*** Second Normal Form (2NF)
    :PROPERTIES:
    :CUSTOM_ID: second-normal-form-2nf
    :ID:       60b8a7ae-54f0-4e4c-851d-ade82bc04724
    :END:

So, the Wikipedia definition is rather dense:

#+BEGIN_QUOTE
  a relation is in 2NF if it is in 1NF and no non-prime attribute is
  dependent on any proper subset of any candidate key of the relation.
  *A non-prime attribute of a relation* is an attribute that is not a
  part of any candidate key of the relation.
#+END_QUOTE

As far as I can tell, 2NF is about removing duplication by minimizing
the number of possible primary keys in the row. There is a rigorous,
mathematical definition for this, but I'm not going that rabbit hole
today.

*** Third Normal Form (3NF)
    :PROPERTIES:
    :CUSTOM_ID: third-normal-form-3nf
    :ID:       4115357e-4fc3-4aff-8b71-2f2d674a0b18
    :END:

3NF has 2 requirements:

- The table/relation (R) must be in 2NF
- Every non-prime attribute of R is non-transitively dependent on every
  key of R.

** An Example
   :PROPERTIES:
   :CUSTOM_ID: an-example
   :ID:       d99e574d-4ff5-4ff3-9244-f98186c6a5fb
   :END:

Lets say I have the following "Customers" table in my database (also
from Wikipedia):

#+BEGIN_HTML
  <table>
#+END_HTML

#+BEGIN_HTML
  <thead>
#+END_HTML

#+BEGIN_HTML
  <tr class="header">
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Customer ID

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

First Name

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Surname

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Telephone Number

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  </thead>
#+END_HTML

#+BEGIN_HTML
  <tbody>
#+END_HTML

#+BEGIN_HTML
  <tr class="odd">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

123

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Pooja

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Singh

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

555-861-2025, 192-122-1111

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  <tr class="even">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

456

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

San

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Zhang

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

555) 403-1659 Ext. 53; 182-929-2929

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       </tr>
     #+END_HTML

     #+BEGIN_HTML
       <tr class="odd">
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     789

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     John

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     Doe

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     555-808-9633

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       </tr>
     #+END_HTML

     #+BEGIN_HTML
       </tbody>
     #+END_HTML

     #+BEGIN_HTML
       </table>
     #+END_HTML

This can be described with the following Persistent entity:

#+BEGIN_EXAMPLE
    Customers
        firstname Text
        surname Text
        telephoneNumber Text
#+END_EXAMPLE

You'll notice this is definitely not /normal/. The telephone column does
not have a format to which all phone numbers conform, therefore there is
no norm. Imagine writing a decoder for the telephone column: it would be
difficult and annoying. We need to normalize this data to make life
easier.

** One-to-Many
   :PROPERTIES:
   :CUSTOM_ID: one-to-many
   :ID:       713a44ab-8e2f-49e0-b227-1b66633af5fa
   :END:

The simplest and most flexible solution is to break up the telephone
column into its own table:

#+BEGIN_HTML
  <table>
#+END_HTML

#+BEGIN_HTML
  <colgroup>
#+END_HTML

#+BEGIN_HTML
  <col width="50%" />
#+END_HTML

#+BEGIN_HTML
  <col width="50%" />
#+END_HTML

#+BEGIN_HTML
  </colgroup>
#+END_HTML

#+BEGIN_HTML
  <tbody>
#+END_HTML

#+BEGIN_HTML
  <tr class="odd">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

#+BEGIN_HTML
  <table>
#+END_HTML

#+BEGIN_HTML
  <caption>
#+END_HTML

Customer Name

#+BEGIN_HTML
  </caption>
#+END_HTML

#+BEGIN_HTML
  <thead>
#+END_HTML

#+BEGIN_HTML
  <tr class="header">
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Customer ID

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

First Name

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Surname

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  </thead>
#+END_HTML

#+BEGIN_HTML
  <tbody>
#+END_HTML

#+BEGIN_HTML
  <tr class="odd">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

123

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Pooja

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Singh

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  <tr class="even">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

456

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

San

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Zhang

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  <tr class="odd">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

789

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

John

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

Doe

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  </tbody>
#+END_HTML

#+BEGIN_HTML
  </table>
#+END_HTML

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

#+BEGIN_HTML
  <table>
#+END_HTML

#+BEGIN_HTML
  <caption>
#+END_HTML

Customer Telephone Number

#+BEGIN_HTML
  </caption>
#+END_HTML

#+BEGIN_HTML
  <thead>
#+END_HTML

#+BEGIN_HTML
  <tr class="header">
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Customer ID

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  <th>
#+END_HTML

Telephone Number

#+BEGIN_HTML
  </th>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  </thead>
#+END_HTML

#+BEGIN_HTML
  <tbody>
#+END_HTML

#+BEGIN_HTML
  <tr class="odd">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

123

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

555-861-2025

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  <tr class="even">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

123

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

192-122-1111

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  </tr>
#+END_HTML

#+BEGIN_HTML
  <tr class="odd">
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

456

#+BEGIN_HTML
  </td>
#+END_HTML

#+BEGIN_HTML
  <td>
#+END_HTML

555) 403-1659 Ext. 53

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       </tr>
     #+END_HTML

     #+BEGIN_HTML
       <tr class="even">
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     456

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     182-929-2929

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       </tr>
     #+END_HTML

     #+BEGIN_HTML
       <tr class="odd">
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     789

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       <td>
     #+END_HTML

     555-808-9633

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       </tr>
     #+END_HTML

     #+BEGIN_HTML
       </tbody>
     #+END_HTML

     #+BEGIN_HTML
       </table>
     #+END_HTML

     #+BEGIN_HTML
       </td>
     #+END_HTML

     #+BEGIN_HTML
       </tr>
     #+END_HTML

     #+BEGIN_HTML
       </tbody>
     #+END_HTML

     #+BEGIN_HTML
       </table>
     #+END_HTML

This establishes a one-to-many relationship between customers and
telephone numbers: as you can see, the =Customer Id= field has =456=
listed twice, . In Persistent this would look like:

#+BEGIN_EXAMPLE
    Customer
        firstname Text
        surname Text

    CustomerTelephone
        customer CustomerId
        telephoneNumber Text
#+END_EXAMPLE

=CustomerId= is a foreign key linking the customer's telephone number to
the customer's name.

** Many-to-Many
   :PROPERTIES:
   :CUSTOM_ID: many-to-many
   :ID:       39975b81-1bfe-4b4a-b9e0-b6d4c4f3968d
   :END:

Breaking up your columns into tables like this also allows for arbitrary
extension. What if, later on, you decide you need addresses for each of
your customers? Doing so is as easy as:

#+BEGIN_EXAMPLE
    Address
       street Text
       city Text
       country Text
       zipcode Text

    CustomerAddress
        customer CustomerId
        address AddressId
        UniqCustomerAddress customer address
#+END_EXAMPLE

=CustomerAddress= is a join table that establishes a many-to-many
relationship; each customer can be linked to multiple addresses, and
vice versa.  

** References, etc.
   :PROPERTIES:
   :CUSTOM_ID: references-etc.
   :ID:       c8161dce-2747-47aa-b5be-3fa9f594af25
   :END:

- [[https://www.yesodweb.com/book/persistent][Yesod Book, Persistent
  Chapter]]
- [[https://github.com/yesodweb/persistent/tree/master/docs#wiki][Persistent
  Wiki]]
- [[https://github.com/yesodweb/persistent/blob/master/docs/Persistent-entity-syntax.md][Persistent
  Entity Syntax]]
- Wikipedia

  - [[https://en.wikipedia.org/w/index.php?title=Database_normalization&oldid=818370313][Database
    normalization]]
  - First normal form
  - Second normal form
  - Third normal form

D clog/strangeloop-2017.md => clog/strangeloop-2017.md +0 -111
@@ 1,111 0,0 @@
---
title: StrangeLoop 2017
date: October 2, 2017
tldr: Lessons and learnings...
---

I recently attended [StrangeLoop 2017][sl]. What follows are some sporadic
thoughts about the conference and community. If you've been on the fence about
going to SL in the past, hopefully this article gives you some insight into what
it's like.

[sl]: https://thestrangeloop.com/

# The Hallway Track

The best talks are the one's you don't expect, or don't think you want to
see. Hallway track is best if you make the effort to actually talk to people. As
an introvert, I default to not making that effort. Theater track is second
best. It's like having Alex Miller (or whoever put the schedule together) pick
the best talks for you. It doesn't actually matter which talks you go to, they
will all be online anyway. So it's actually best *not* to make a schedule nor
pick talks ahead of time, just let the randomness present new ideas to you. It's
a lot of fun.

# The Venue and Location

...is beautiful. The hotel and opera house in which the conference is hosted are
superb, and the staff that handles the logistics of food, coffee, and tea setup,
room monitoring, and A/V are first-class. Seriously, props to them for making
the conference go so smoothly. I've been on that end of the conference work (for
other, much smaller conferences) and I know it can be difficult.

Strange Loop takes place in downtown St Louis, basically walking distance from
the Arch and the Cardinals' ballpark. The Arch was closed this year, but the
Cards happened to be playing at home that weekend so I went to a game, which I
highly recommend, it's a great stadium if you're into baseball.

# Some of my favorite talks

- Coming soon

# The Politics

Diversity was great, the [Alloy Project][alloy] seems to be working, and I think
that is a very good thing. I was actually surprised by the different types of
people I saw; it's different from the typical nerdy-white-male demographic that
have dominated the teams that I've worked on and grown used to. Even as a
nerdy-white-male myself, there is only so much masculine-monoculture I can stand
(which is one reason why I usually retreat into headphones with soft music
playing when working in an office, and prefer to work from home). Diversity is
simply more interesting than monoculture when you have to deal with people on a
daily basis...

[alloy]: https://www.projectalloy.org/

The overall political bent of the conference was rather liberal-centrist, which
was only exacerbated by the corporate overtones of the sponsors. I was hoping
for a more left-leaning politics because I've been reading a lot of
poststructuralist philosophy lately and was hoping to talk about it with
techies, but I didn't really meet anyone brave enough to really broach the
subject with (e.g. Deleuze's work, when combined with from Alan Turing, makes
for some fun new concepts). None of the sponsors seemed interesting to me as a
mostly-independent developer. Maybe I didn't give them much of a chance because
they all seemed to be trying to entice developers with freebies and I've learned
to [despise the free lunch][lunch], or maybe I avoided all the sponsor-booths
due to my bias against Monsanto's monoculture-inducing agricultural practices
([PDF](http://www.fooledbyrandomness.com/pp2)).

[lunch]: https://books.google.com/books?id=P_zMW3EHnTEC&lpg=PP1&dq=48%20laws%20of%20power&pg=PR15#v=onepage&q=48%20laws%20of%20power&f=false

Not that I'm inherently against large companies. But the cost structure seems to
be geared toward larger companies. I remember last year (2016) there was a
company pricing tier such that companies could send entire groups of developers
for some batch pricing. I don't remember the details and can't find much
historical pricing info on the website, so maybe the actual situation is
different than my perception of it.

In any case, I always like to see incentives for independent developers, not
incentives for large companies. I value independent devs becuase they put their
own skin on the line. They will often take time out of their own schedule - time
that they could be making good money - and write open source software that other
developers _and companies_ rely on. For example, in my experience, the [Clojars
maintainers][clojars] achieve a better [uptime][uptime] than many internal Maven
repos.

[clojars]: https://github.com/clojars/clojars-web/wiki/Contact
[uptime]: http://status.clojars.org/

An example of a great indy dev is [Chas Emerick][chas], who actually gave a
(last-minute) talk at PWL Conf (I can't find the video unfortunately). He
contributes a ton to the Clojure community in addition to running [his own
company][pdfdata] (at least, I _think_ he's the only person working on that; in
any case he's still putting his skin in the game). There are many more
developers out there like this. [Matt Mitchell][matt] gave a [talk][] in which
he basically went through a bunch of ways that you as a developer could get
started writing code for the public good. Each example he gives requires you to
find a real problem in the world and then propose a solution. This is miles away
from the typical corporate-developer workflow of picking a user story off of the
board, writing some unit tests for the described functionality, and then moving
bits around until the test suite passes. The typical corporate-developer has no
skin in the game and thereby has no effect on the real world, which effectively
renders their opinions about the world useless, pragmatically speaking. I think
its a rather depressing affair when compared to the jubilee of starting a
company or foundation of some kind. My point is that, if a developer would like
to escape the corporatism, the wider community should provide support and
incentives to do so.

[matt]: https://twitter.com/geminiimatt
[talk]: https://www.youtube.com/watch?v=2Cm3N4Yi3b0
[chas]: https://github.com/cemerick
[pdfdata]: https://www.pdfdata.io/

M index.org => index.org +0 -3
@@ 2,9 2,6 @@
#+author: Ben Sima
#+email: ben@bsima.me
#+options: author:nil toc:nil num:nil
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/normalize.css"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/typography.css"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/print.css" media="print"/>

Hi, my name is Ben Sima. I'm a student of philosophy, biology, and mathematics.


M now.org => now.org +0 -3
@@ 3,9 3,6 @@
#+author: Ben Sima
#+email: ben@bsima.me
#+options: toc:nil email:t num:nil
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/normalize.css"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/typography.css"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/print.css" media="print"/>

I'm currently living in San Diego, but in the process of moving to Palo Alto.


M resume.org => resume.org +0 -3
@@ 2,9 2,6 @@
#+author: Ben Sima
#+email: ben@bsima.me
#+options: toc:nil email:t num:nil
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/normalize.css"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/typography.css"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/print.css" media="print"/>
#+html_head: <link rel="stylesheet" type="text/css" href="assets/css/resume.css"/>

Hi! I'm a software engineer currently located in San Diego (moving to the Bay