How Building GUI App with Lisp
The Case of Pocket Change, Inc.
LISP MEETUP #50 Mar 27, 2017
I’m Eitaro Fukamachi
@nitro_idiot fukamachi
Joined Pocket Change in Feb 1
Pocket Change
http://www.pocket-change.jp
Available at Haneda Airport
Today’s topic
What I want to tell today
What I don’t tell
How we use Common Lisp in our work
How you can use Common Lisp in your work
Touch Screen
Coins Bills
IC Card Reader
Receipt Printer
API Server
Touch Screen
Coins Bills
IC Card Reader
Receipt Printer
API Server
Building the next version of this software
is my work.
How to build
Pocket Change
• Windows OS (Rich!)
• Fullscreen GUI application
We decided to use Electron
https://electron.atom.io
by
Web Server
(Express)
Main Process
(Node.js)
Open
Web Server
(Express)
Main Process
(Node.js)
Open
Web Server
(Express)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Open
Web Server
(Express)
Main Process
(Node.js)
Bidirectional Communication
Renderer Process
(Chromium)
React.js
Why Electron?
• Easy to deploy
• Can package into a single EXE installer
• Can build GUI with Web technologies
• Embedded Chromium
However
The language is JavaScript. 👎
Why can’t we use Common Lisp?
None
(just a launcher)
Main Process
(Node.js)
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Spawn
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Common Lisp Process
(SBCL)
Spawn
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Common Lisp Process
(SBCL)
Spawn
Bidirectional Communication
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Common Lisp Process
(SBCL)
Spawn
Bidirectional Communication
+ Common Lisp
Make an SBCL executable and bundle it
Looks a quite easy trick, huh? :)
How communicating
between CL and Browser
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Common Lisp Process
(SBCL)
Spawn
Bidirectional Communication
+ Common Lisp
Open
None
(just a launcher)
Main Process
(Node.js)
Renderer Process
(Chromium)
React.js
Common Lisp Process
(SBCL)
Spawn
Bidirectional Communication
+ Common Lisp
Communication between CL and Browser
• MUST be bidirectional
• MUST be asynchronous
• MUST be easy to handle with JavaScript
• SHOULD be real-time
We decided to use JSON-RPC
• Small specification
• Not depends on a specific transport layer
• We use WebSocket
• http://jsonrpc.org
• https://github.com/fukamachi/jsonrpc
JSON-RPC
--> {"jsonrpc": “2.0",
"method": “subtract",
"params": [42, 23],
"id": 1}
Request
JSON-RPC
--> {"jsonrpc": “2.0",
"method": “subtract",
"params": [42, 23],
"id": 1}
Request
<-- {"jsonrpc": “2.0",
"result": 19,
"id": 1}
Response
JSON-RPC
--> {"jsonrpc": “2.0",
"method": “subtract",
"params": [42, 23],
"id": 1}
Request
<-- {"jsonrpc": “2.0",
"result": 19,
"id": 1}
Response
--> {"jsonrpc": “2.0",
"method": “update",
"params": [1,2,3,4,5]}
Notification
(Request without “id”)
How to structure
GUI Application with Electron
No best practices (yet)
to build an Electron app.
In our case
Renderer Process
Store
View
ActionReducer
Flux Architecture
functionfunctionfunctionfunction
functionfunctionfunctionfunctionfunctionfunctionfunction
Renderer Process
Store
View
ActionReducer
Flux Architecture
Common Lisp
JSON-RPC server
functionfunctionfunction
functionfunctionfunction
← JSON-RPC over WebSocket →
Not only
Browser Common Lisp
Coin Counter IC Card Reader Printer
API Server
Benefits of Flux + JRPC Architecture
• JavaScript part is just a UI renderer
• Business logics are all in Common Lisp
• Common Lisp functions are easy to test
• Other components are also easy to test
• Because they all talk in JSON-RPC
How to develop the app
Development
• You can use your machine (Mac, Linux, etc)
• Virtual devices are used while development
• Easy to make a mock of components
Development
1. Run a Electron process (npm run dev)
2. Open REPL of the Common Lisp process

from Emacs with Swank
3. Enjoy
Packaging
1. Run Windows in Virtual Environment
2. npm run package
3. Wait
Experiments
Coin Counter IC Card Reader Printer
API Server
Coin Counter IC Card Reader Printer
API Server
Hard to share data.
“brain”, the central storage
• All data(state) are in Common Lisp part
• What service the user chose?
• How much money is in the user’s IC card?
• How many coins are in?
• etc.
• It’s just a hash-table (with thread-lock).
“Propagation Class”
Metaclass for synchronize data between components
“Propagation Class”
(defclass user ()
((balance :initarg :balance
:accessor user-balance)
(coins :initarg :coins
:accessor user-coins))
(:metaclass propagation-class))
“Propagation Class”
(defclass user ()
((balance :initarg :balance
:accessor user-balance)
(coins :initarg :coins
:accessor user-coins))
(:metaclass propagation-class))
(defmethod on-update ((user user)
slot-name)
(declare (ignore slot-name))
(notify “browser”
“user/update-state” user))
“Propagation Class”
(defvar *user*
(make-instance ‘user …)))
;; Notify this modification
;; to the browser implicitly.
(setf (user-balance *user*) 1730)
Bless the Meta Object Protocol.
So,
Why Common Lisp?
Why Common Lisp?
• We ♥ Common Lisp :)
• Good for writing unknown/complicated
applications.
• Interactive development with REPL.
Thanks.

Building GUI App with Electron and Lisp