CHP is a work in progress. It is a Clojure Domain Specific Langage (DSL) I designed to teach kids server-side web development with Clojure. It is designed to be as easy to learn as PHP but better by leveraging the power of Clojure. Let's see if I have succeeed in this goal
Getting started with PHP is easy. PHP is a templating language: HTML strings are surrounded with PHP code. CHP borrows this philosophy, but instead of HTML strings, Hiccup is used. Hiccup is a DSL using Clojure data structures to represent HTML. There are several implementation of Hiccup both on the server-side and client-side. The original implementation of Hiccup is created by Weave Jester There is a client side implementation of Hiccup called Sablono that can be used for react.js components instead of JSX. CHP has its own implementation of Hiccup called Ikota
This blog itself is written with CHP. The best way to get started is to clone this blog and play with the code.
% git clone https://sonwh98@bitbucket.org/sonwh98/lambdakids.git
% cd lambdakids
% ./scripts/start.sh
Open the URL in the browser http://localhost:3000
You can also connect to the server socket REPL running on port 5555.
% telnet localhost 5555
Hiccup Examples
Hiccup maps very well to HTML because both are forms of s-expressions. Clojure's form of s-expressions is called EDN . Hiccup is just plain EDN. Here are examples of Hiccup and how it maps to HTML.
[:h1 "hello" 1 2] => <h1> hello 1 2</h1>
[:div {:style {:background-color :red}} => <div style="background-color: red">
[:span "a" "b" "c"] <span> a b c </span>
[:a {:href "http://google.com"} "Google"] <a href="http://google.com">Google</a>
[:img {:width 100 :height 150 <img width="100px" height="150px"
:src "/images/fractal.jpg"}]] src="/images/fractal.jpg"/>
</div>
[:tag {:attribute-1 value-1
:attribute-2 value-2}
child-1 child-2 ... child-n] => <tag attribute-1=value-1
attribute-2=value-2>
child-1
child-2
...
child-n
</tag>
What is the advantage of using Hiccup over HTML?
Hiccup is Clojure data structures and not ordinary strings. Because Hiccup is just regular Clojure data structures, you have the full power of the Clojure language to manipulate, transform and construct data structures which ultimately will be transformed into HTML. Hiccup + Clojure functions for data manipulation and transformation creates a more powerful templating language than PHP
For example, the following clojure code generates hiccup data which is ultimately transforms into HTML
[:ul {:style {:color :red}} [:ul {:style {:color :red}} <ul style="color: 'red'">
(for [i (range 3)] => ([:li 0] => <li> 0 </li>
[:li i])] [:li 1] <li> 1 </li>
[:li 2])] <li> 2 </li>
</ul>
Why is CHP better than PHP?
Let's look at the PHP version
<ul>
<?php foreach( range(0, 3) as $i): ?>
<li> <?php echo $i ?> </li>
<?php endforeach; ?>
</ul>
CHP version is cleaner because it is pure Clojure data structures with a concise and consistent syntax. Everything is an expression. Even the for list comprehension is an expression that evaluates to a data structure. In contrast, the PHP version is more verbose, has an inconsistent syntax containing a mix of HTML strings (not data structures) and embedded PHP code (also not data structures) which must be escaped using a special syntax.
One of the biggest complaints about programming in Clojure or any LISP dialect is keeping those damn parenthesis balanced. However, a text editor that understands how to format and manipulate s-expressions eliminates this problem.
What is structural editing?
Structural editing is manipulation of code as data structures and not simple strings. Emacs with paredit plugin is a structural editor. I will use emacs to teach but you can use any text editor that can manipulate s-expressions. Intellij with Cursive plugin is another editor that can manipulate s-expressions. Without a good structural editor, writing LISP code is painful and frustrating
Starting emacs
% emacs
The first time you start emacs, it will install packages specified in ~/.emacs.d/init.el and you will see some warnings. Ignore the warnings. If you get errors exit emacs and start emacs again. To exit emacs, use the keyboard shortcut ctrl-x ctrl-c. This means keep finger on ctrl key while pressing x and then c key. You may need to exit and restart emacs several times before all packages are installed without errors.
All of emacs plugins are actually written in a dialect of LISP called emacs LISP. Emacs is a LISP Machine implemented in software
Cider
Cider is an emacs plugin making Clojure development easier by interfacing emacs to the REPL. Refer to Cider documentation for more details
Paredit
Paredit is an emacs plugin that does structual editing of s-expressions. There are others like parainfer and smarparens . I recommend Paredit only because its what I'm most familar with and works for me. Feel free to explore other options. Using Paredit (or any structural editor) well is key to making programming in a LISP efficient otherwise you will get lost in the parenthesis. Here are some resources on Paredit:
Magit
Magit is an git plugin for emacs. Here's a Magit Cheatsheet
Frequently used keyboard shortcuts
In table below, C stands for the Ctrl key. M stands for Meta key which is usually bound to the the ESC or ALT key
Action | Keyboard Shortcuts |
---|---|
Start a shell within emacs | M-x shell |
Exit | C-x C-c |
Open File | C-x C-f |
Find a file in project | M-x ffip |
Mark a region | C-space |
Copy a text region into memory | M-w |
Cut line/s-expression | C-k |
Paste memory | C-y |
Move down a line | C-n |
Move up a line | C-p |
Move to beginning of line | C-a |
Move to end of line | C-e |
Move to next s-expression | M-f |
Move back to previous s-expression | M-b |
Cut an s-expression | C-k |
Format code selection | C-A-\ |
Evaluate s-expression | C-x C-e |
Evaluate buffer | C-c-k |
Switch namespace | C-c M-n |
Switch Buffer | C-b |
Move Cursor between Windows | C-x o |
Split Buffer Vertically | M-1 |
Split Buffer Horizontally | M-2 |
Move between windows | C-x o |
Start and connect to REPL (jack in) | M-x cider-jack-in |
Slurp an s-expression | C-right-arrow |
Barf an s-expression | C-left-arrow |
Delete an s-expression | C-d |
Resize windows using doremi | C-x t w |