1
1
![ cljs] ( img/cljs.png )
2
2
3
- > __ If you just wanna try something __ , check out the [ interactive tutorial ] ( http://chimeces.com/cljs-browser-repl/ ) .
3
+ Translations: [ 中文 ] ( README.zh.md ) .
4
4
5
- Hello, this is my attempt at a very concise guide to ClojureScript's syntax!
6
- ClojureScript is a Lisp dialect for front-end web development. It compiles to
7
- JavaScript for use in the browser.
5
+ > __ 如果你注释想试试__ , 可以看看这个[ 交互式教程] ( http://chimeces.com/cljs-browser-repl/ ) .
8
6
9
- ClojureScript is fundamentally different from JavaScript and other
10
- compile-to-JS languages like Dart, CoffeeScript, and TypeScript. It uses a
11
- more powerful yet simpler syntax. There are other differences not related
12
- to syntax, such as default immutability to combat the "new spaghetti code"
13
- that is mutatable stateful objects, and sane state management allowing language-level data-binding.
7
+ Hello, 我在在尝试给 ClojureScript 语法写一份简明的教程.
8
+ ClojureScript 是一门适用于 Web 前端开发的 Lisp 方言, 它被编译到 JavaScript 在浏览器中使用.
14
9
15
- I believe that ClojureScript's largest barrier to entry for beginners is
16
- probably the foreign nature of its syntax. I hope to explain it as plainly and
17
- succinctly as possible with this guide.
10
+ ClojureScript 在根本上就和 JavaScript 或者其他编译到 JavaScript 的语言不一样, 比如和 Dart, CoffeeScript 和 TypeScript.
11
+ 它使用了更强大的语法, 但也更简单. 也有一些其他一些语法之外的区别,
12
+ 比如说默认采用不可变性, 用来解决状态可变的对象造成"新型 spaghetti code",
13
+ 同时提供正常的状态管理功能用来实现语言级别的数据绑定.
18
14
19
- > __ Also__ , check out [ Parinfer] if you want a simpler way to manage parentheses in ClojureScript.
15
+ 我相信对于新手来说 ClojureScript 最大的障碍在于他令人感到陌生的语法.
16
+ 在这份教程里, 我希望能尽可能平常并且简洁解释一遍.
17
+
18
+ > __ 同时__ , 如果你需要为 ClojureScript 找一个更简单的管理括号的方案, 请了解一下 [ Parinfer] .
20
19
21
20
[ Parinfer ] :http://shaunlebron.github.io/parinfer/
22
21
23
- ## Syntax
22
+ ## 语法
24
23
25
- There is __ literal data __ :
24
+ 这是 __ literal data(字面量数据) __ :
26
25
27
26
``` clj
28
- ; number
27
+ ; number(数字)
29
28
1.23
30
29
31
- ; string
30
+ ; string(字符串)
32
31
" foo"
33
32
34
- ; keyword (like strings, but used as map keys )
33
+ ; keyword(关键字, 就像字符串, 但是用于 map 的键 )
35
34
:foo
36
35
37
- ; vector ( array)
36
+ ; vector(向量, 或者说数组, array)
38
37
[:bar 3.14 " hello" ]
39
38
40
- ; map ( associative array)
39
+ ; map(关联数字, associative array)
41
40
{:msg " hello" :pi 3.14 :primes [2 3 5 7 11 13 ]}
42
41
43
- ; set (distinct elements)
42
+ ; set(distinct elements, 元素唯一 )
44
43
#{:bar 3.14 " hello" }
45
44
```
46
45
47
- And there is __ symbolic data __ :
46
+ 这是 __ symbolic data(符号化数据) __ :
48
47
49
48
``` clj
50
- ; symbol (represents a named value )
49
+ ; symbol(符号, 表示一个有名字的值 )
51
50
foo
52
51
53
- ; list (represents a "call ")
52
+ ; list(链表, 表示一次"调用 ")
54
53
(foo :bar 3.14 )
55
54
```
56
55
57
- #### Evaluation
56
+ #### 求值
58
57
59
- ClojureScript can evaluate data to create a new "value" from it .
58
+ ClojureScript 可以对数据求值从而创建出新的"数值" .
60
59
61
- 1 . Literal data evaluates to itself, of course :
60
+ 1 . 字面量数据求值之后得到自身, 显然地 :
62
61
63
62
``` clj
64
63
1.23 ; => 1.23
65
64
" foo" ; => "foo"
66
65
[:bar 3.14 " hello" ] ; => [:bar 3.14 "hello"]
67
66
```
68
67
69
- 1. A __symbol__ evaluates to the value bound to it :
68
+ 1. __符号__求值之后得到绑定在上面的数值 :
70
69
71
70
```clj
72
71
foo ; => 3
73
72
```
74
73
75
- 1. A __list__ evaluates to the return value of a " call " .
74
+ 1. __list__求值之后得到 " 调用 " 的结果 .
76
75
77
76
```clj
78
77
(+ 1 2 3 ) ; => 6
79
78
(= 1 2 ) ; => false
80
79
(if true " y" " n" ) ; => "y"
81
80
```
82
81
83
- #### Calls
82
+ #### 调用
84
83
85
- If the first element of a list is a __function__, then the rest of the elements
86
- are evaluated and passed to it ([prefix notation](http://en.wikipedia.org/wiki/Polish_notation )).
84
+ 如果列表的第一个元素是一个__函数__, 那么其余元素会被求值并传给它 ([prefix notation](http://en.wikipedia.org/wiki/Polish_notation )).
87
85
88
86
```clj
89
- ; String concatenate function
87
+ ; 字符串合并函数
90
88
(str " Hello " " World" ) ; => "Hello World"
91
89
92
- ; Arithmetic functions
93
- (= a b) ; equality (true or false)
94
- (+ a b) ; sum
95
- (- a b) ; difference
96
- (* a b c) ; product
90
+ ; 运算函数
91
+ (= a b) ; 等式 (true 或者 false)
92
+ (+ a b) ; 求和
93
+ (- a b) ; 求差
94
+ (* a b c) ; 求积
97
95
(< a b c) ; true if a < b < c
98
96
99
- ; Evaluation Steps
100
- (+ k (* 2 4 )) ; assume k evalutes to 3
101
- (+ 3 (* 2 4 )) ; (* 2 4) evaluates to 8
102
- (+ 3 8 ) ; (+ 3 8) evalutes to 11
97
+ ; 求值步
98
+ (+ k (* 2 4 )) ; 这里假设 k 求值得到 3
99
+ (+ 3 (* 2 4 )) ; (* 2 4) 求值得到 8
100
+ (+ 3 8 ) ; (+ 3 8) 求值得到 11
103
101
11
104
102
```
105
103
106
- If the first element of a list is one of the language's few __ special forms__ ,
107
- then the rest of the elements are passed to it unevaluated. (There are only [ 22
108
- special forms] ( https://clojure.org/reference/special_forms ) .)
104
+ 如果列表的第一个元素是一个__ 特殊形式(Special Form)__ , 那么其余元素传递给它时不做求值.
105
+ (总共有 [ 22 的特殊形式] ( https://clojure.org/reference/special_forms ) .)
109
106
110
107
``` clj
111
- (if (= a b c) ; <-- determines if a=b=c
112
- (foo 1 ) ; <-- only evaluated if true
113
- (bar 2 ) ; <-- only evaluated if false
108
+ (if (= a b c) ; <-- 判断是否 a=b=c
109
+ (foo 1 ) ; <-- 只在 true 的时候求值
110
+ (bar 2 ) ; <-- 只在 false 的时候求值
114
111
)
115
112
116
- ; define k as 3
117
- (def k 3 ) ; <-- notice that k is not evaluated here
118
- ; (def needs the symbol k, not its value )
113
+ ; 定义( define) k 为 3
114
+ (def k 3 ) ; <-- 注意这个 k 不会被求值
115
+ ; (def 需要 k 这个符号, 而不是它的值 )
119
116
120
- ; make a greeting function
121
- (fn [username] ; <-- expected parameters vector
117
+ ; 创建一个 greeting 函数
118
+ (fn [username] ; <-- 期望参数是 Vector 格式的
122
119
(str " Hello " username))
123
120
124
121
; oops, give the function a name
@@ -128,99 +125,90 @@ special forms](https://clojure.org/reference/special_forms).)
128
125
(greet " Bob" ) ; => "Hello Bob"
129
126
```
130
127
131
- If the first element of a list is a __ macro__ , then the rest of the elements
132
- are passed to it unevaluated, but the resulting value of the call is evaluated.
133
- Let's illustrate that difference with the following diagram:
128
+ 如果列表的第一个元素是个 __ Macro__ , 那么其余元素传给它时不做求值,
129
+ 但是调用之后的结果是经过求值. 用下面这个图形对它们的区别做一下展示:
134
130
135
131
![ calls] ( img/calls.png )
136
132
137
- This difference in evaluation allows macros to act as code-generating
138
- functions. For example, the ` defn ` macro expands to ` def ` and ` fn ` , as we used
139
- separately in a previous example:
133
+ 求值过程上的区别使得 Macro 可以作为生成代码的函数使用.
134
+ 比如 ` defn ` 这个 Macro 展开成前面例子中遇到的 ` def ` 和 ` fn ` :
140
135
141
136
``` clj
142
- ; create a named function using the defn macro
137
+ ; 用 defn 这个 Macro 创建一个具名函数
143
138
(defn greet [username]
144
139
(str " Hello " username))
145
140
146
- ; the definition for the defn macro (over-simplified )
141
+ ; defn 这个 Macro 的定义(极度简化版本 )
147
142
(defmacro defn [name args body]
148
143
`(def ~name (fn ~args ~body)))
149
144
```
150
145
151
- __ App developers rarely need to create their own macros__ , but it is an
152
- indispensible tool for the library developer to give app developers the full
153
- flexibility of the language.
146
+ __ 应用开发者极少需要为他们自己创建 Macros__ , 但这项功能对于类库开发者来说是不可或缺的,
147
+ 通过 Macro 他们可以为应用开发者提供语言本身最大的灵活性.
154
148
155
- #### Simple substitutions
149
+ #### 简单的替换
156
150
157
- There are a few [ macro characters] ( http://clojure.org/reader#The%20Reader--Macro%20characters ) that help make the language succinct
158
- by performing simple substitutions (not full macros):
151
+ 有几个 [ Macro 字符] ( http://clojure.org/reader#The%20Reader--Macro%20characters ) 被用来提供简单的替换, 让语言变得更简洁(不全是 Macro).
159
152
160
153
``` clj
161
- ; short-hand for creating a simple function:
154
+ ; 简单的函数的一种简写
162
155
; #(...) => (fn [args] (...))
163
156
164
157
#(* 3 %) ; => (fn [x] (* 3 x))
165
158
166
159
#(* 3 (+ %1 %2 )) ; => (fn [x y] (* 3 (+ x y)))
167
160
```
168
161
169
- ## That's it for Syntax
162
+ ## 就这些语法了
170
163
171
- You need to know more than syntax to be proficient in a language, of course .
172
- But you should now know enough to be comfortable looking around at examples and
173
- reasoning about how data is being evaluated and passed around:
164
+ 要熟练使用 ClojureScript 当然是需要了解更多的语法的 .
165
+ 不过了解了上面这些语法, 你应该可以比较舒服地查看各种例子了,
166
+ 也可以看出来数据是怎么被求值的, 怎么被到处传递的.
174
167
175
168
``` clj
176
- ; printing to the javascript console
169
+ ; 在 Console 中打印
177
170
(js/console.log " Hello World!" )
178
171
179
- ; creating local bindings (constants )
172
+ ; 创建局部的绑定(常量 )
180
173
(let [a (+ 1 2 )
181
174
b (* 2 3 )]
182
175
(js/console.log " The value of a is" a)
183
176
(js/console.log " The value of b is" b))
184
177
185
- ; generate a sequence of numbers
178
+ ; 创建数字的序列
186
179
(range 4 ) ; => (0 1 2 3)
187
180
188
- ; generate first four multiples of 3
181
+ ; 生成前 4 个自然数乘以 3 的结果
189
182
(map #(* % 3 ) (range 4 )) ; => (0 3 6 9)
190
183
191
- ; count elements in a sequence
184
+ ; 序列中的元素个数
192
185
(count " Bob" ) ; => 3
193
186
(count [4 5 2 3 ]) ; => 4
194
187
195
- ; select three letter names from a list
188
+ ; 从列表中筛选出三个字母组成的名字
196
189
(def names [" Bob" " David" " Sue" ])
197
190
(filter #(= (count %) 3 ) names) ; => ("Bob" "Sue")
198
191
```
199
192
200
- (Don't worry about getting lost in parentheses. All modern text editors will
201
- highlight the corresponding ones and will indent your code automatically for
202
- readability, as is standard in every other language.)
193
+ (需要担心圆括号太多而迷失. 所有的现代文本编辑器都可以做到配对的括号的高亮, 甚至自动缩进代码来保证可读性, 就跟其他语言标准的做法一样.)
203
194
204
- ## ClojureScript vs JSX in HTML templating
195
+ ## HTML 模板语法中的 ClojureScript 对比 JSX
205
196
206
- See [ Jumping from HTML to ClojureScript] ( https://github.com/shaunlebron/jumping-from-html-to-clojurescript ) to see how ClojureScript's syntax solves the verbosity/flexibility problems faced in the JS community by [ JSX] .
197
+ 阅读 [ Jumping from HTML to ClojureScript] ( https://github.com/shaunlebron/jumping-from-html-to-clojurescript ) 来了解 ClojureScript 语法怎样解决 JavaScript 社区中 JSX 解决的冗长性(verbosity?)和灵活性的问题 .
207
198
208
199
[ Jumping from HTML to ClojureScript ] :https://github.com/shaunlebron/jumping-from-html-to-clojurescript
209
200
[ JSX ] :https://facebook.github.io/react/docs/jsx-in-depth.html
210
201
211
- ## A complete reference
202
+ ## 完整的手册
212
203
213
- The syntax section of the [ ClojureScript API reference] is a comprehensive look at
214
- the possible syntax forms and even shows the source code for how each are read/parsed.
204
+ [ ClojureScript API 手册] 的语法章节可以找到所有可能的语法形式, 甚至能从源码中找到怎样进行读取和解析.
215
205
216
206
[ syntax section ] :https://github.com/cljsinfo/cljs-api-docs/blob/catalog/INDEX.md#syntax
217
- [ ClojureScript API reference ] :http://cljs.github.io/api
207
+ [ ClojureScript API 手册 ] :http://cljs.github.io/api
218
208
219
- ## Useful Resources
209
+ ## 实用资源
220
210
221
- Here are the resources and steps that I took while learning ClojureScript.
222
- (Most resources covering Clojure also apply to ClojureScript, since they
223
- share a significant subset with each other.)
211
+ 下面是我在学习 ClojureScript 时候的一些资源和步骤. (大部分介绍 Clojure 的资源对于 ClojureScript 也适用, 因为两者共享了很大的交集.)
224
212
225
213
1 . Reading through the [ ClojureScript Wiki] ( https://github.com/clojure/clojurescript/wiki )
226
214
1 . Reading the book [ ClojureScript Up and Running] ( http://synrc.com/publications/cat/Functional%20Languages/Clojure/Oreilly.ClojureScript.Up.and.Running.Oct.2012.pdf )
@@ -236,4 +224,3 @@ share a significant subset with each other.)
236
224
1 . Experimenting in < http://clojurescript.net/ > for ClojureScript REPL with a browser context.
237
225
1 . Reading docstrings of functions I encounter with ` (doc <funcname>) ` in REPL.
238
226
1 . [ Miscellaneous ClojureScript things to know] ( https://github.com/shaunlebron/ClojureSheet#clojurescript-stuff )
239
-
0 commit comments