Hello World #
一、第一个Clojure程序 #
1.1 使用REPL #
最简单的方式是在REPL中运行:
bash
clj
clojure
user=> (println "Hello, World!")
Hello, World!
nil
1.2 创建项目 #
使用Leiningen创建项目:
bash
lein new hello-world
cd hello-world
1.3 编写代码 #
编辑 src/hello_world/core.clj:
clojure
(ns hello-world.core)
(defn -main []
(println "Hello, World!"))
1.4 运行程序 #
bash
lein run
输出:
text
Hello, World!
二、程序结构解析 #
2.1 命名空间声明 #
clojure
(ns hello-world.core)
ns定义命名空间hello-world.core是命名空间名称- 对应文件路径
src/hello_world/core.clj
2.2 函数定义 #
clojure
(defn -main []
(println "Hello, World!"))
分解说明:
| 部分 | 含义 |
|---|---|
defn |
定义函数的宏 |
-main |
函数名(主函数约定) |
[] |
参数向量(空表示无参数) |
(println ...) |
函数体 |
2.3 S表达式 #
Clojure使用S表达式(S-expression)语法:
clojure
(操作符 操作数1 操作数2 ...)
示例:
clojure
(+ 1 2 3)
(println "Hello")
(str "Hello" " " "World")
2.4 前缀表示法 #
Clojure使用前缀表示法(波兰表示法):
clojure
(+ 1 2)
(- 10 3)
(* 2 3 4)
(/ 10 2)
优势:
- 无运算符优先级问题
- 支持多参数
- 一致性强
三、语法基础 #
3.1 注释 #
clojure
(println "Hello")
(println "World")
(comment
(println "This is not executed")
(+ 1 2 3))
3.2 数据字面量 #
clojure
42
3.14
"Hello"
\A
true
false
nil
:keyword
'symbol
'(1 2 3)
[1 2 3]
{:a 1 :b 2}
#{1 2 3}
3.3 符号命名规则 #
clojure
(def my-variable 10)
(def my-function +)
(def *important* true)
(def ->json identity)
(defn my-function? [x] true)
约定:
- 使用kebab-case(短横线分隔)
- 谓词函数以
?结尾 - 危险操作以
!结尾 - 常量使用
*星号*
3.4 块表达式 #
do 用于组合多个表达式:
clojure
(do
(println "Step 1")
(println "Step 2")
(println "Step 3")
"done")
返回最后一个表达式的值。
四、函数定义详解 #
4.1 基本函数定义 #
clojure
(defn greet [name]
(str "Hello, " name "!"))
(greet "Clojure")
4.2 多参数函数 #
clojure
(defn add [a b]
(+ a b))
(defn greet-person [first-name last-name]
(str "Hello, " first-name " " last-name))
(greet-person "John" "Doe")
4.3 可变参数 #
clojure
(defn sum [& numbers]
(apply + numbers))
(sum 1 2 3 4 5)
(defn greet-all [greeting & names]
(str greeting ", " (clojure.string/join ", " names)))
(greet-all "Hello" "Alice" "Bob" "Carol")
4.4 多参数列表 #
clojure
(defn greet
([name]
(greet "Hello" name))
([greeting name]
(str greeting ", " name "!")))
(greet "Alice")
(greet "Hi" "Bob")
4.5 文档字符串 #
clojure
(defn square
"Returns the square of a number.
Usage: (square 5) => 25"
[x]
(* x x))
(doc square)
五、变量定义 #
5.1 def #
def 用于定义全局变量:
clojure
(def pi 3.14159)
(def message "Hello, World!")
(defn circle-area [r]
(* pi (* r r)))
5.2 let #
let 用于局部绑定:
clojure
(let [x 10
y 20]
(+ x y))
(let [a 1
b (+ a 2)
c (+ b 3)]
[a b c])
5.3 常量 #
clojure
(def ^:const MAX-VALUE 100)
(def ^:const DEFAULT-TIMEOUT 5000)
六、执行方式 #
6.1 REPL执行 #
bash
clj
clojure
user=> (defn hello [] (println "Hello!"))
user=> (hello)
Hello!
nil
6.2 脚本执行 #
创建 script.clj:
clojure
(println "Running as script")
(println (+ 1 2 3))
执行:
bash
clj -M script.clj
6.3 主函数执行 #
在 project.clj 中指定:
clojure
(defproject hello "0.1.0"
:main hello.core)
运行:
bash
lein run
6.4 编译执行 #
bash
lein uberjar
java -jar target/hello-0.1.0-standalone.jar
七、代码组织 #
7.1 命名空间 #
clojure
(ns my-app.core
(:require [clojure.string :as str])
(:use [clojure.set])
(:import [java.util Date]))
(defn current-time []
(str (Date.)))
7.2 require #
clojure
(ns my-app.core
(:require [clojure.string :as str]))
(str/upper-case "hello")
(ns my-app.core
(:require [clojure.string :refer [upper-case lower-case]]))
(upper-case "hello")
7.3 import #
clojure
(ns my-app.core
(:import [java.util Date ArrayList]
[java.io File]))
(defn now []
(Date.))
(defn list-files [path]
(.listFiles (File. path)))
八、REPL开发流程 #
8.1 交互式开发 #
clojure
user=> (defn greet [name] (str "Hello, " name))
#'user/greet
user=> (greet "World")
"Hello, World"
user=> (defn greet [name] (str "Hi, " name "!"))
#'user/greet
user=> (greet "World")
"Hi, World!"
8.2 加载文件 #
clojure
user=> (load-file "src/my_app/core.clj")
user=> (use 'my-app.core :reload)
8.3 查看文档 #
clojure
user=> (doc println)
user=> (find-doc "string")
user=> (source map)
九、常见错误 #
9.1 括号不匹配 #
clojure
(defn add [a b]
(+ a b))
(defn add [a b]
(+ a b))
9.2 符号未定义 #
clojure
user=> (unknown-symbol)
Syntax error compiling at (REPL:0:0).
Unable to resolve symbol: unknown-symbol in this context
9.3 参数数量错误 #
clojure
user=> (+ 1)
ArityException Wrong number of args (1) passed to: core/+
9.4 类型错误 #
clojure
user=> (+ 1 "a")
ClassCastException java.lang.String cannot be cast to java.lang.Number
十、总结 #
第一个Clojure程序的关键点:
- S表达式:
(操作符 操作数...) - 前缀表示法:无优先级问题
- 函数定义:
defn 名称 [参数] 函数体 - 命名空间:
ns声明
Clojure程序特点:
- 语法简洁统一
- 代码即数据
- 函数是一等公民
- 交互式开发体验
准备好深入学习REPL交互环境了吗?让我们继续!
最后更新:2026-03-27