UP | HOME
Land of Lisp

Zhao Wei

How can man die better than facing fearful odds, for the ashes of his fathers and the temples of his Gods? -- By Horatius.

Learn data-structure-and-algorithm in functional programming

1. The Decision to Make

I begin my journey as a programming by seriously study computer science in 2016. During that time, I know nothing about programming and just have a blur idea about what is programming: it is about making class, call API, do some web development.


During study, I was trained rigorously at Otago university by studying Java first, then move to use C to learn data structure and algorithm. After that, during my graduate study, I learned to use C++ to do computer graphics task. After graduation, I went to a company which use JavaScript and TypeScript to do all the jobs. In general, my programming world is all around OOP, design pattern, different gotchas (C++ takes the credit). My attetion is about how to build an app or implement some algorithm from some paper by folloing the fomula listed. It is a word full of complicated syntax, state management and the conventions around them which have been built for decades.


I guess I would not be aware of functinal programming if I didn’t meet Shane Mulligan and his passion about Emacs. From that moment, I was keep pulling away from my previous track. From Emacs, to Elisp, from Elisp to other lisp especially Common-Lisp. I was taking on a path of functional prgramming.


At first, I am not aware of this effect. However, I gradually discovered that I am just not interested in C-like programming anymore, or even jobs using them. Because I am interested in how they work and why they work, instead of using them to call some APIs or following instructions to get a number. I am very curious about how things could be constructed such that they are right to describe the steps of achieving something.


During the path of chasing such goal, there are 2 languages make me very excited that they changes how I view programming: one is Lisp, another is Erlang.


For Lisp, its simplicity and yet so powerful to express anything in itself makes me wonder why people just stop teaching it at university(at least most of them). It is just sad that so few people really give it a try and so many people just consider it is old, outdated and powerless.


If Lisp changed me how I view code and data, how expressive and yet so simple a language could be. Then Erlang is the language changed me about how to implement complicated system using message-passing. First time, I understand the power of REAL OOP(it is about message passing, not the Java bullshit).


There are plenty of ariticles about Lisp and Erlang, I will not explain their power in detail. The important thing is different programming language indeed changed how I view programming forever. However, as I dive deeper into the world of FP, I somehow feel vulnerable and not confident. Gradually, I realized that what I am missing is the way to describe data sturcture and algorithm once I mastered during rigorous trainning from C world. Therefore, if I want to keep living in functional world, I have to be free to express algorithm in functional style. I have to make the decision to devour the hard part of FP.

2. Material to study

Different from C-like language, the data structure and algorithm are expressed differently in FP. More than that, there are very few book and course about teaching algorithm in FP. After search, I found these two seems promising:

That is right, another functional programming to learn. But it is not a problem if you are using Emacs.

3. Emacs support for OCaml

  • Install OCaml

    # Install OCaml package manager
    sudo apt install opam ()
    
    # Use OCaml package to install dependency
    opam install caml-mode merlin ocp-indent
    
  • Elisp configuration for tuareg, merlin, and merlin-company

    (add-to-list 'load-path "~/.opam/system/share/emacs/site-lisp/")
    
    (when (executable-find "ocaml")
      (when (maybe-require-package 'tuareg)
        (autoload 'tuareg-mode "tuareg" "Major mode for editing Caml code" t)
        (autoload 'ocamldebug "ocamldebug" "Run the Caml debugger" t)
        (autoload 'caml-mode "caml" "Major mode for editing OCaml code." t)
        (autoload 'run-caml "inf-caml" "Run an inferior OCaml process." t)
    
        (add-to-list 'auto-mode-alist '("\\.ml[iylp]?$" . tuareg-mode))
        (add-to-list 'auto-mode-alist '("\\.topml$" . tuareg-mode))
        (add-to-list 'interpreter-mode-alist '("ocamlrun" . caml-mode))
        (add-to-list 'interpreter-mode-alist '("ocaml" . caml-mode))
    
        (add-hook 'tuareg-mode-hook
                  (lambda ()
                    (define-key tuareg-mode-map (kbd "C-c C-c") 'tuareg-eval-phrase)
                    (define-key tuareg-mode-map (kbd "C-c C-e") 'tuareg-eval-region)))
        (after-load 'tuareg
          (set-face-attribute 'tuareg-font-double-semicolon-face nil
                              :foreground "#ffb86c"))
    
        (if window-system
            (progn
              (require 'caml-font)
              (set-face-foreground 'caml-font-doccomment-face "#cb4b16"))))
    
      (when (maybe-require-package 'ocp-indent)  
        (setq ocp-indent-path
              (concat
               (replace-regexp-in-string "\n$" ""
                                         (shell-command-to-string "opam config var bin")) "/ocp-indent"))
        (setq ocp-indent-config "strict_with=always,match_clause=4,strict_else=never"))
    
      (when (maybe-require-package 'merlin)
        (autoload 'merlin-mode "merlin" "Merlin mode" t)
        (require 'caml-types nil 'noerror)
    
        (setq merlin-use-auto-complete-mode 'easy)
        (setq merlin-command 'opam)
        (setq merlin-error-on-single-line t)
    
        (add-hook 'tuareg-mode-hook #'merlin-mode)
        (add-hook 'caml-mode-hook #'merlin-mode))
    
    
      (when (maybe-require-package 'merlin-company)
        (add-hook 'caml-mode-hook
                  (lambda ()
                    (setq-local company-backends (zw/add-to-company-backends company-backends 'merlin-company-backend))))))
    
  • OCaml is even supported from Org-babel

    print_string "Hello World"
    
    Hello World- : unit = ()
    

Shane, thank you so much for leading me into Emacs world and functional programming.

4. References