summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/article/clj0.md (renamed from content/article/tutorial-clj-0.md)3
-rw-r--r--content/article/clj1.md (renamed from content/article/tutorial-clj-1.md)3
-rw-r--r--content/article/clj2.md (renamed from content/article/tutorial-clj-2.md)25
-rw-r--r--content/article/clj3.md (renamed from content/article/tutorial-clj-3.md)5
4 files changed, 26 insertions, 10 deletions
diff --git a/content/article/tutorial-clj-0.md b/content/article/clj0.md
index 444ba2aa..2473f968 100644
--- a/content/article/tutorial-clj-0.md
+++ b/content/article/clj0.md
@@ -1,7 +1,8 @@
+++
title = 'Coffee Break Clojure, Vol.0'
subtitle = '初识 Clojure 与 Lisp'
-slug = 'tutorial-clj-0'
+slug = 'clj0'
+aliases = '/article/tutorial-clj-0/'
tags = ["Lisp","编程"]
categories = '茶歇蔻芥'
date = 2026-09-15 22:58:43
diff --git a/content/article/tutorial-clj-1.md b/content/article/clj1.md
index 6ead5a50..3f043afb 100644
--- a/content/article/tutorial-clj-1.md
+++ b/content/article/clj1.md
@@ -1,7 +1,8 @@
+++
title = 'Coffee Break Clojure, Vol.1'
subtitle = '准备工具'
-slug = 'tutorial-clj-1'
+slug = 'clj1'
+aliases = ['/article/tutorial-clj-1']
tags = ["Lisp","编程"]
categories = '茶歇蔻芥'
date = 2026-09-19 01:45:49
diff --git a/content/article/tutorial-clj-2.md b/content/article/clj2.md
index 3bfd5983..a5d6207c 100644
--- a/content/article/tutorial-clj-2.md
+++ b/content/article/clj2.md
@@ -1,7 +1,8 @@
+++
title = 'Coffee Break Clojure, Vol.2'
subtitle = "Forms O' Plenty"
-slug = 'tutorial-clj-2'
+slug = 'clj2'
+aliases = '/article/tutorial-clj-2/'
tags = ["Lisp","编程"]
categories = '茶歇蔻芥'
date = 2026-09-25 18:43:53
@@ -129,6 +130,19 @@ a
(+ 1 num))
```
+你可能注意到了 Clojure 函数和非 Lisp 语言的另一个区别:没有 `return` 语句。函数如果有多个并列的形式,就会以最后一个形式的值作为函数的返回值。
+
+做个习题,下面这段函数调用为什么返回了 `nil`?
+
+```clojure
+(defn chatty-add [a b]
+ (let [result (+ a b)]
+ result
+ (println result)))
+
+(chatty-add 1 2) ;; => nil
+```
+
## Lambda 形式
Lambda 形式类似 JavaScript 里的立即执行函数,也就是定义一个匿名函数,然后立马执行它,这样就可以限定变量的作用域。
@@ -189,18 +203,17 @@ Lambda 形式的操作符不是指向函数的符号,就是函数本身。
你发现了吗?我们做了一步完全多余的运算。根本不需要计算 `(> a 1)` 为 `false`,只要算出 `(> b 1)` 为 `true`,就可以算出整个 `or` 形式的值为 `true`,因为逻辑运算或只要求其中一个值为真。
-如果 `or` 是函数,就必须做那一步多余的运算,否而得不到值,无法调用函数。然而,有些运算是有副作用的,比如从消息队列中取出一条消息,会导致其他人无法再次从队列中取到它,若 `or` 运算丢弃了这条消息,只采用了其中一条,数据就丢失了。
+如果 `or` 是函数,就必须做那一步多余的运算,否而得不到值,无法调用函数。然而,有些运算是有副作用的,比如从消息队列中取出一条消息,会导致其他人无法再次从队列中取到它,若 `or` 运算丢弃了这条消息,数据就丢失了。
那怎么办呢?有什么办法可以让参数不被预先求值吗?
-有的,答案就是宏(macro)。宏这个机制被不少语言借鉴,比如 Rust 和 Haskell(在 Haskell 里叫 Template,模板),其实本质就是对还没求值的列表做预处理。
+答案就是宏(macro)。宏这个机制被不少语言借鉴,比如 Rust 和 Haskell(在 Haskell 里叫 Template,模板),其实本质就是对还没求值的列表做预处理。
定义宏就是定义一系列对列表做变换的规则,宏作为形式的操作符时,会先进行宏展开(macroexpand),然后对展开的结果求值。宏展开之前,所有的列表都不会被求值。
我们来看看 `or` 这个宏的定义:
```clojure
-
(defmacro or
([] nil)
([x] x)
@@ -245,7 +258,7 @@ Lambda 形式的操作符不是指向函数的符号,就是函数本身。
```
<details>
- <summary>如果 `fn` 是函数的解释</summary>
+ <summary>如果 <code>fn</code> 是函数的解释</summary>
首先对 `[a b c]` 求值,解释器会发现 `a` 这个符号不存在,然后报错。
@@ -351,7 +364,7 @@ Clojure 没有用编译器实现解构,而是用 `destructure` 函数实现的
现在你应该知道求值 Clojure 形式时,解释器底下大概都发生了什么,你应该也熟悉了一些基本的函数、宏和特殊形式,比如 `let` `if` 和 `fn`,可以写一些简单的 Clojure 程序了。
-其实除了本文提到的四种形式,Clojure 还可以用特定类型的数据作为操作符,也可以当作一种类型的形式。这要留到下篇讲了。
+其实除了本文提到的四种形式,Clojure 还可以用特定类型的数据作为操作符(比如用一个集合做操作符,用于查看参数是否存在于集合内),也可以当作一种类型的形式。这要留到下篇讲了。
下一篇我们要了解 Clojure 里的集合数据类型,分别是我们已经见过的列表(list)和向量(vector),此外还有集合(set)和映射(map)。我们还会讲到如何操作这些集合,包括遍历和筛选等等。我们还会了解到惰性序列(Lazy sequence),然后你就可以写程序处理相对复杂的数据,并且能够到同时做到语法简洁和高性能。这些都是后话了。
diff --git a/content/article/tutorial-clj-3.md b/content/article/clj3.md
index 237d8527..80475c32 100644
--- a/content/article/tutorial-clj-3.md
+++ b/content/article/clj3.md
@@ -1,7 +1,8 @@
+++
title = 'Coffee Break Clojure, Vol.3'
subtitle = '只用圆括号怎么够?'
-slug = 'tutorial-clj-3'
+slug = 'clj3'
+aliases = '/article/tutorial-clj-3'
tags = ["Lisp","编程"]
categories = '茶歇蔻芥'
date = 2026-09-25T20:17:41+08:00
@@ -251,7 +252,7 @@ Clojure 的映射写起来和 JSON 很像。
:key3 nil}
```
-
+https://www.brainonfire.net/files/seqs-and-colls/main.html
## 井号和集合