When functions are called, they are usually stored on the call stack, a part of memory, and the size of the call stack matters when it comes to a recursive function. Here is a function that returns a sum of numbers at a given number n such that sum = n + (n-1) + (n-2) ... 0 in which the number of function calls is O(n).

; this is an example in racket version
(define (sum n)
    (if (= x 0)
        0
        (+ x (sum (- n 1)))))

The above function will evaluate in this way.

sum(5)
5 + sum(4)
5 + (4 + sum(3))
5 + (4 + (3 + sum(2)))
5 + (4 + (3 + (2 + sum(1))))
5 + (4 + (3 + (2 + 1)))
15

If the large nubmer is fed, then the call stacks will be filled up quickly and eventually raise a Runtime error.

Then, how can we tackly this problem? Use acc!

(define (sum n)
    (define (sum-helper n acc)
        ; just simply return acc when n becomes 0
        (if (= n 0)
            acc
            (+ acc (sum-helper (- n 1)))))
    (sum-helper n 0)

Now, look at the call stacks below.

sum-helper(5, 0)
sum-helper(4, 5)
sum-helper(3, 9)
sum-helper(2, 12)
sum-helper(1, 14)
sum-helper(0, 15)
15

In functional programming, the tail-recursive way is a key technique so it is very important to practice converting recursive functions to tail-recursive functions.

Let’s say that there is a function called getHalf.

-- it halfs when even number is given 
getHalf x = 
  if even x
  then Just (x `div` 2)
  else Nothing

This function does not work if we feed wrapped values, for example, Just 3. To solve it, we should use bind(>>=) operator.

> Just 5 >>= half
Nothing
> Just 10 >>= half
Just 5

Monad is a typeclass.

class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b

And Maybe is a Monad.

instance Monad Maybe where
  Nothing >>= func = Nothing
  Just val >>= func = func val

Maybe is a Functor and also a Monad!

The Maybe data type looks like this.

data Maybe a = Nothing | Just a

Functors

You can’t just apply a normal function like (*5) to Maybe data type. This is where fmap comes handy. Because fmap knows how to apply the function.

> fmap (*5) (Just 1)
Just 5
> fmap (*5) Nothing
Nothing

But.. How? Here is the answer! Functor is a typeclass. It is any data type that defines how fmap applies to it.

class Functor f where
  fmap :: (a -> b) -> f a -> f b

Maybe is a Functor! This is the main reason that fmap knows how to apply.

instance Functor Maybe where
    fmap f (Just val) = Just (f val)
    fmap f Nothing = Nothing

List is also a Functor!

instance Functor [] where
    fmap = map

Practice

The data type WhyNot defined as follows:

data WhyNot a = Nah | Sure a
    deriving Show

Let’s make WhyNot into an instance of Functor and Monad.

-- definitions
fmap :: Functor f => (a -> b) -> f a -> f b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
return :: Monad m => a -> m a

instance Functor WhyNot where
    fmap _ Nah = Nah
    fmap f (Sure x) = f x

instance Monad WhyNot where
    return Sure

    Nah >>= _ = Nah
    (Sure x) >>= f = f x

Managing History

Git Log

# options are add to display better
$ git log --oneline --decorate --graph --all -30

Git Show

# display the commit info and a diff
$ git show 770b1ab6

Undoing

Amending Commits

# incorporate "Gemfile.lock" into the previous commit
$ git add Gemfile.lock
$ git commit --amend --no-edit

# edit the commit msg
$ git commit --amend

NOTE
Git creates a new commit object when use amend.

Unstaging Files

$ git status --short
 M Gemfile
 M Gemfile.lock
 A TODO.md

# undo the staging file
$ git reset TODO.md

Undoing a Commit

# remove the commit from the history and revert to the point where the files were staged
$ git reset --soft HEAD^

More

Git Stash

git stash is a command that it stores all of the changes away. What so great about is that you can come back to the code anytime that you had stashed away. So I recommend to use it when there is an emergency bugfix.

# use -u flag to grab everything and get back to an empty status 
$ git stash -u

Tmux is the terminal multiplexer. According to its site:

It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more.

Installation

I am an OS X user so I could simply install it using Homebrew. I believe it is available on any system because it is a popular package.

$ brew install tmux
$ brew info tmux

Customizing tmux configuration

You can specify configuration settings in .tmux.config file. With these customization, it’s easy to get Tmux to work exactly the way you want it to.

# .tmux.config

# Replace C-b with C-s for the prefix key
unbind C-b
set -g prefix C-s
bind-key -r C-s send-prefix

# Easy reloading of the tmux.conf configuration file
bind-key r source-file ~/.tmux.conf \; display-message "~/.tmux.conf reloaded"

# Seamless aviation using vim-tmux-navigator (github christoomey/vim-tmux-navigator)
is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"'
bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L"
bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D"
bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U"
bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R"
bind -n C-\ if-shell "$is_vim" "send-keys C-\\" "select-pane -l"

# Restore clear screen keybind mapped over by tmux-navigator
bind C-l send-keys C-l

# Use 256 color mode, useful for Vim colorshemes
set-option -g default-terminal "screen-256color"

# Use emacs / readline key-bindings in the tmux command prompt
set-option -g status-keys "emacs"

# Allow the session name in status left to display up to 50 characters
set-option -g status-left-length 50

# More useful status-right with battery percentage and nicely formated datetime
set -g status-right "#(battery -t -g black)  #(date '+%a, %b %d - %I:%M') "

# More intuitive pane splitting key-bindings, open all in current path
bind-key - split-window -v  -c '#{pane_current_path}'
bind-key \ split-window -h  -c '#{pane_current_path}'
bind c new-window -c '#{pane_current_path}'

# Easy resizing of panes with fine and coarse adjustment
bind -n S-Left resize-pane -L 2
bind -n S-Right resize-pane -R 2
bind -n S-Down resize-pane -D 1
bind -n S-Up resize-pane -U 1
bind -n C-Left resize-pane -L 10
bind -n C-Right resize-pane -R 10
bind -n C-Down resize-pane -D 5
bind -n C-Up resize-pane -U 5

# Number windows starting at 1, renumber as windows are added / removed
set-option -g base-index 1
set-option -g renumber-windows on

bind-key b break-pane -d

# Use vim keybindings in copy mode
setw -g mode-keys vi

# Setup 'v' to begin selection as in Vim
bind-key -t vi-copy v begin-selection
bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"

# Update default binding of `Enter` to also use copy-pipe
unbind -t vi-copy Enter
bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"

# Sample quick-pane configurations
bind-key h split-window -h "htop"
bind-key t split-window -h -c ~/ "vim todo.md"
bind-key w split-window -h -c ~/my-wiki "vim +CtrlP"

# Fuzzy matching session navigation via fzf utility
bind C-j split-window -v "tmux list-sessions | sed -E 's/:.*$//' | grep -v \"^$(tmux display-message -p '#S')\$\" | fzf --reverse | xargs tmux switch-client -t"

# Prompted join-pane
bind-key j command-prompt -p "join pane from: "  "join-pane -h -s '%%'"

# Easily swap a pane (targeted by pane number) with the current pane
bind-key s display-panes\; command-prompt -p "pane #: "  "swap-pane -t '%%'"

# "break session" and "kill session" without exiting tmux
bind-key C-b send-keys 'tat && exit' 'C-m'
bind-key K run-shell 'tmux switch-client -n \; kill-session -t "$(tmux
display-message -p "#S")" || tmux kill-session'