owned this note
owned this note
Published
Linked with GitHub
# 用 ClojureScript 做前端開發的體驗 - 陳涌(題葉)
{%hackmd j86FNbMoRoeN4Xn0pg5ofw %}
> 請從這裡開始
[silde](https://gist.github.com/jiyinyiyong/b403a24667a3f2b93afdd6e9f57f6f10)
# First impressionㄎs
CoffeScript -> Haskell -> React -> ClojureScript
# Clojure
Clojure 在 2007 年發佈,Clojure 是一個在 JVM 平台上的語言 (JVM語言還有 Scala、Gradle、Kotlin、JRuby、JPython...等)
ClojureScript 在 2011年發佈,將 Clojure 透過 Google Closure Compiler 編譯為 JavaScript。
# Functianal Programming
- Higher-order function (like lodash)
- pure functions
- immutable
- every thing is an expression, DSL (LISP macro, code is data)
- lazy
補充:
- code is data 是 LISP 最特別的地方,不算是 FP 的特產。
- 因為 LISP 的特性,LISP 系的語言有 meta programming 的功能
- [Why is the programming language Lisp special?](https://www.quora.com/Why-is-the-programming-language-Lisp-special)
# ClojureScript Feature
- Compile 到其它平台 (Clojure -> JVM, ClojureScript -> JavaScript)
- LISP, Macro
- Immutablity
- Dynamic Typed
- Data-oriented
- Simplicity [Simple made easy](https://www.youtube.com/watch?v=34_L7t7fD_U)
# Where to use ClojureScript
- JavaScript platforms: browsers, Node.js , React Native.
- Scripting, data manipulation. Data-oriented language.
- Creating Virtual DOM, states management.
# My tiny apps in ClojureScript
- [respo](http://respo.site/)
- [cirru](http://cirru.org/)
# ClojureScript: syntax and toolchains
## Lumo: a REPL
- 透過 Google Closure Compiler (JavaScript Version)
- 不需要 JVM (快!)
- node platform
[lumo](https://github.com/anmonteiro/lumo)
# Basic
- S-expression
- list 中第一個 symbol 會被 eval,其它 symbol 會成為參數
```clojure
(+ 1 1) ; => 2
(not true) ; => false
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
(if false "a" "b") ; => "b"
(map inc [1 2 3]) ; => (2 3 4)
(reduce + [1 2 3 4])
; = (+ (+ (+ 1 2) 3) 4)
; => 10
(def x 1)
; The [] is the list of arguments for the function.
(defn hello [name]
(str "Hello " name))
(hello "Steve") ; => "Hello Steve"
(fn [] "Hello World") ; => fn
(def stringmap {"a" 1, "b" 2, "c" 3})
(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
```
補充:
```clojure
'(+ 1 2) ; quote 表示 list, quote is a special form
(list + 1 2) ; 也可以用 list function 產生 list
(+ 1 1) ; list 如果沒有加 quote ,第一個 symobl 會被當成 function 而 eval,用 JavaScript 改寫就會長: +.apply([1 1])
(def x 1) ; def 是一個 special form,改寫為 JavaScript : var x = 1;
(fn [] "Hello World") ;; 產生 lambda 的方法之一
```
Clojure / ClojureScript 內建 4 種 data container
- list, e.g. (1 2 3)
- vector, e.g. [1 2 3]
- hash-map, e.g. {:first 1 :second 2 :third 3}
- set, e.g. #{"never" "repeat"}
# Difference with pure functianal language
- 不 pure (有 side effect)
- 沒有 type system (和 haskell or OCaml 相比)
# Difference with JavaScript
- LISP syntax (S-expression)
- tail recursions (no for/while)
- immutablities
- Static analysis (lkie TypeScript)
- Different compilers and communities
- package may be on Clojars or npm
# ClojureScript Compiler
- Google Closure Compiler (非主流)
- 用 goog.madule 定義 module
```javascript=
goog.module(‘foo’);
var Quux = goog.require(‘baz.Quux’);
exports.Bar = function() { /* … */ };
```
# More Toolchains
- leiningen + figwheel (JVM)
- boot + figwheel (JVM)
- shadow-cljs (JVM)
- lumo (node)
- planck (webkit JavaScriptCore)
# Why ClojureScript
## React Concepts
react 的設計有很多從 Functional Language 借來的想法,
用 Functional Language 寫 React 更 make sense !
p.s. Facebook 開發了 [ReasonML](https://github.com/facebook/reason)
## JavaScript Problems
- No immutabable
- No type checking
- less pure in function
## React side-effects vs ClojureScript version
## immptable-js code is tedious
```javascript=
// ES6
const {profile, image, age, gender} = this.props.client;
// ImmutableJS
const profile = Immutable.get(this.props.client, 'profile');
const image = Immutable.get(this.props.client, 'image');
const age = Immutable.get(this.props.client, 'age');
const gender = Immutable.get(this.props.client, 'gender');
```
p.s. javascript maybe immer today ?
## ClojureScript data
ClojureScript support immptabable by default !
## conditional rendering in JSX
在 cljs 可以直接用 if, switch/case
js 中會 return undefined 所以不能直接寫 if
## Clojurescript Atoms and swap!
```clojure
; Here's a simple counter using an atom
(def atom-int (atom 1))
(swap! atom-int inc) ; @x is now 2
(reset! atom-int 100) ; @x is now 100
(swap! atom-int inc) ; @x is now 101
```
# ClojureScript Experence
## Dynamic typing
- dynamic data
- type 的問題 可以用 clojure spec
ClojureScript 目前 support [Clojure Spec](https://clojure.org/guides/spec) 完成 run time type checking
## Macros
pipe operator (-> & ->>) 在 ClojureScript 可以任意使用,
- 沒有 type 所以要小心
## tail recursions
因為沒有 for/while ,所以思維要轉換一下。
## immutable data
Clojure 中 data structure 原本就是 immutable ,
- Presistent data structure, structural sharing
## Introp
在 ClojureScript 中要用 js 的 function 要用 js/ 的 namespace
e.g.
```clojure=
(.log js/console "Hello World")
```
- await/async 完整支援還在討論中 (await/async proposal)[https://clojureverse.org/t/async-generator-functions-in-cljs-requesting-feedback/2262]
p.s. ClojureScript 中原本有 core.async 的解決方案
## npm module
shadow-cljs 中能較方便使用 npm 的 module
能用 CommonJS 和 ES6 的語法
# Debugging ClojureScript
## shadow-cljs
(shadow-cljs)[http://shadow-cljs.org/]
- 使用 shadow-cljs 中會用到一個定義文件 shadow-cljs.edn
- shadow-cljs 可以說是 ClojureScript 中的 webpack
## hot code swapping
- defonce 保存 global state
## Static analysis & warnings
[cljs-devtools](https://github.com/binaryage/cljs-devtools)
## ClojureScript 是編成 JS 語言中最好的語言 !
[@pesterhazy](https://twitter.com/pesterhazy/status/1011347727836483586)
# demo
[minimal-shadow-cljs-browser](https://github.com/minimal-xyz/minimal-shadow-cljs-browser)
# 括號的問題
- 有很多工具可以讓括號編輯 (Emacs ! )
- 講者用 calcit-editor
補充:
[Parinfer](https://shaunlebron.github.io/parinfer/)
# Communities
- [Forum](http://clojureverse.org)
- [Reddit](https://reddit.com/r/Clojure/)
- [Slack][http://clojurians.slack.com/)
- [中文論壇](http://clj.im/)
補充:
[ClojureTW](https://clojure.tw/)