Guile/Scheme 编程教程 / 第1章:Guile 概述
第 1 章:Guile 概述
1.1 什么是 Guile
Guile(GNU Ubiquitous Intelligent Language for Extensions)是 GNU 项目官方推荐的扩展语言。它的名字本身就是一个双关语——在英语中 “guile” 意为"狡诈、机智",恰好体现了 Lisp 家族语言灵活多变的特性。
Guile 的核心定位:
| 角色 | 说明 |
|---|---|
| 独立脚本语言 | 可编写完整的应用程序和脚本 |
| 嵌入式扩展语言 | 通过 C API 嵌入到 C/C++ 程序中 |
| GNU 生态核心组件 | GnuCash、GDB、GNU Mailutils 等均使用 Guile 扩展 |
| Guix 系统配置语言 | GNU Guix 操作系统的包管理和系统配置均使用 Guile 编写 |
1.2 Scheme 语言标准
Guile 实现了多个 Scheme 标准,理解这些标准对于正确使用 Guile 至关重要。
1.2.1 标准演进时间线
| 标准 | 年份 | 状态 | Guile 支持 |
|---|---|---|---|
| R4RS | 1991 | 早期标准 | 完全兼容 |
| R5RS | 1998 | 经典标准 | 完全兼容 |
| R6RS | 2007 | 大型标准 | 部分兼容(通过模块) |
| R7RS-small | 2013 | 现代标准 | 大部分兼容 |
| R7RS-large | 进行中 | 扩展标准 | 逐步支持中 |
1.2.2 R5RS:经典基础
R5RS 是最广泛使用的 Scheme 标准,也是 Guile 的核心基础。它定义了:
;; R5RS 核心特性演示
;; 1. 词法作用域 (lexical scoping)
(define x 10)
(let ((x 20))
x) ; => 20
x ; => 10(外层绑定不受影响)
;; 2. 一等函数 (first-class functions)
(define (apply-twice f x)
(f (f x)))
(apply-twice (lambda (n) (* n 2)) 3) ; => 12
;; 3. 尾递归优化 (tail-call optimization)
(define (factorial n acc)
(if (<= n 1)
acc
(factorial (- n 1) (* n acc))))
(factorial 10 1) ; => 3628800
;; 4. 连续 (continuations) —— Guile 通过 call/cc 支持
(+ 1 (call/cc
(lambda (k)
(+ 2 (k 3))))) ; => 4
1.2.3 R6RS:模块与库
R6RS 引入了标准化的库系统和更严格的语义规范:
;; R6RS 风格的库定义(Guile 中通过模块实现类似功能)
;; 在 Guile 中,我们使用 define-module 替代 R6RS 的 library
(define-module (my-math basic)
#:export (square cube))
(define (square x) (* x x))
(define (cube x) (* x x x))
注意:Guile 并未完全实现 R6RS,而是选择性地吸收了其中优秀的设计。在实际开发中,建议使用 Guile 原生的模块系统而非 R6RS 库。
1.2.4 R7RS-small:现代化改进
R7RS-small 在保持 Scheme 简洁性的同时引入了一些实用特性:
;; R7RS 特性示例
;; 定义记录类型 (record type)
;; Guile 通过 srfi-9 提供类似功能
(use-modules (srfi srfi-9))
(define-record-type <point>
(make-point x y)
point?
(x point-x)
(y point-y))
(define p (make-point 3 4))
(point-x p) ; => 3
(point-y p) ; => 4
;; 命名 let(Guile 原生支持)
(let loop ((i 0) (acc '()))
(if (= i 5)
(reverse acc)
(loop (+ i 1) (cons i acc))))
; => (0 1 2 3 4)
1.3 GNU 扩展特性
Guile 在标准 Scheme 基础上提供了丰富的 GNU 扩展,使其更适合实际工程使用。
1.3.1 核心扩展概览
| 扩展类别 | 特性 | 说明 |
|---|---|---|
| 模块系统 | define-module / use-modules | 比 R6RS 库更灵活 |
| 字符串扩展 | SRFI-13 字符串库 | 完整的字符串操作 API |
| 正则表达式 | POSIX 正则 | (ice-9 regex) |
| 进程管理 | system* / pipe | 调用外部程序 |
| 网络编程 | Socket API | TCP/UDP 网络通信 |
| 并发编程 | 线程、通道、期货 | (ice-9 threads) |
| 哈希表 | SRFI-69 | 键值对数据结构 |
| JSON/YAML | 第三方库 | 数据序列化 |
1.3.2 实用扩展示例
;; 1. 字符串处理(SRFI-13)
(use-modules (srfi srfi-13))
(string-join '("Hello" "Guile" "World") "-")
; => "Hello-Guile-World"
(string-contains "Hello Guile World" "Guile")
; => 6
;; 2. 正则表达式
(use-modules (ice-9 regex))
(define m (string-match "([0-9]+)\\.([0-9]+)" "version 3.0.5"))
(match:substring m 0) ; => "3.0"
(match:substring m 1) ; => "3"
(match:substring m 2) ; => "0"
;; 3. 哈希表
(define ht (make-hash-table))
(hash-set! ht 'name "Guile")
(hash-set! ht 'version 3)
(hash-ref ht 'name) ; => "Guile"
(hash-ref ht 'version) ; => 3
;; 4. 进程调用
(use-modules (ice-9 popen))
(use-modules (ice-9 textual-ports))
(let* ((port (open-input-pipe "uname -a"))
(output (get-string-all port)))
(close-pipe port)
(display output))
1.3.3 SRFI 扩展标准
SRFI(Scheme Requests for Implementation)是 Scheme 社区的标准扩展库。Guile 内置支持大量 SRFI:
| SRFI 编号 | 名称 | 功能 |
|---|---|---|
| SRFI-1 | 列表库 | 高级列表操作 |
| SRFI-9 | 记录类型 | define-record-type |
| SRFI-13 | 字符串库 | 字符串操作 |
| SRFI-14 | 字符集 | 字符集操作 |
| SRFI-26 | 剪裁 | cut/cute 部分应用 |
| SRFI-31 | 递归 | rec 表达式 |
| SRFI-38 | 外部表示 | 共享结构的读写 |
| SRFI-41 | 流 | 惰性流 |
| SRFI-43 | 向量库 | 向量操作 |
;; SRFI 使用示例
;; SRFI-1: 列表操作
(use-modules (srfi srfi-1))
(filter even? '(1 2 3 4 5 6)) ; => (2 4 6)
(iota 5) ; => (0 1 2 3 4)
(take '(1 2 3 4 5) 3) ; => (1 2 3)
(drop '(1 2 3 4 5) 3) ; => (4 5)
(fold + 0 '(1 2 3 4 5)) ; => 15
;; SRFI-26: 部分应用(cut)
(use-modules (srfi srfi-26))
(map (cut * 2 <>) '(1 2 3 4 5)) ; => (2 4 6 8 10)
(map (cut list 1 <> 3) '(a b c)) ; => ((1 a 3) (1 b 3) (1 c 3))
;; SRFI-31: 递归命名表达式
(use-modules (srfi srfi-31))
(rec (fact
(lambda (n)
(if (<= n 1) 1 (* n (fact (- n 1))))))
(fact 10)) ; => 3628800
1.4 Guile 与 Common Lisp 对比
对于有 Lisp 背景的开发者,理解 Guile Scheme 与 Common Lisp 的差异至关重要。
1.4.1 核心设计哲学对比
| 特性 | Guile Scheme | Common Lisp |
|---|---|---|
| 设计哲学 | 最小化、优雅 | 实用、大而全 |
| 作用域 | 纯词法作用域 | 词法 + 动态作用域 |
| 命名空间 | 单一命名空间 | 独立的函数/变量命名空间 |
| 宏系统 | 卫生宏 (syntax-rules) | defmacro(非卫生) |
| 真值 | 除 #f 外皆为真 | T 和 NIL |
| 可变性 | 默认不可变 | 默认可变 |
| 标准 | R5RS/R6RS/R7RS | ANSI Common Lisp |
| 实现 | 单一实现 | 多种实现(SBCL、CLISP 等) |
1.4.2 语法差异示例
;; ============== Guile Scheme ==============
;; 函数定义
(define (greet name)
(string-append "Hello, " name "!"))
;; 条件表达式
(define (describe n)
(cond
((< n 0) "negative")
((= n 0) "zero")
(else "positive")))
;; 命名 let(循环惯用法)
(let loop ((i 0))
(when (< i 5)
(display i) (newline)
(loop (+ i 1))))
;; 多值返回
(define (divmod a b)
(values (quotient a b) (remainder a b)))
(call-with-values
(lambda () (divmod 17 5))
(lambda (q r)
(format #t "~a 余 ~a~%" q r)))
;; ============== Common Lisp ==============
;; 函数定义 —— 需要显式声明函数
(defun greet (name)
(format nil "Hello, ~a!" name))
;; 条件表达式
(defun describe (n)
(cond
((< n 0) "negative")
((= n 0) "zero")
(t "positive"))) ;; T 而非 else
;; 循环 —— 使用 loop 宏
(loop for i from 0 below 5
do (format t "~a~%" i))
;; 多值返回
(defun divmod (a b)
(values (floor a b) (mod a b)))
(multiple-value-bind (q r)
(divmod 17 5)
(format t "~a 余 ~a~%" q r))
1.4.3 选择建议
| 场景 | 推荐 | 原因 |
|---|---|---|
| GNU 工具扩展 | Guile | 原生支持 |
| 学习函数式编程 | Guile Scheme | 更简洁、更纯粹 |
| 大型工业项目 | Common Lisp | 生态更成熟 |
| 嵌入式脚本 | Guile | C API 更友好 |
| 数值计算 | Common Lisp | 类型声明优化 |
| 操作系统配置 | Guile (Guix) | 原生集成 |
1.5 适用场景
1.5.1 典型应用领域
1. 应用程序扩展脚本
┌─────────────────────────────────┐
│ 主程序 (C/C++) │
│ ┌───────────────────────────┐ │
│ │ Guile 解释器嵌入 │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ 用户脚本 (.scm) │ │ │
│ │ │ - 自定义规则 │ │ │
│ │ │ - 插件系统 │ │ │
│ │ │ - 配置扩展 │ │ │
│ │ └─────────────────────┘ │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
2. 使用 Guile 的知名项目
| 项目 | 用途 | 说明 |
|---|---|---|
| GnuCash | 金融软件 | 使用 Guile 编写报表和业务规则 |
| GDB | 调试器 | Python/Guile 脚本扩展 |
| LilyPond | 乐谱排版 | Guile 作为核心配置语言 |
| GNU Guix | 包管理器 | 系统配置完全用 Guile 编写 |
| GNU Make | 构建工具 | 实验性 Guile 扩展 |
| TeXmacs | 编辑器 | Guile 作为插件语言 |
3. 业务场景示例:配置文件处理
;; 使用 Guile 作为配置语言,替代 YAML/JSON
;; config.scm
(define *server-config*
'((host . "0.0.0.0")
(port . 8080)
(workers . 4)
(database
. ((adapter . "postgresql")
(host . "localhost")
(port . 5432)
(name . "myapp")))
(logging
. ((level . "info")
(file . "/var/log/app.log")))))
;; 配置读取函数
(define (config-get config key)
(let ((entry (assq config key)))
(if entry (cdr entry) #f)))
;; 使用示例
(config-get *server-config* 'port) ; => 8080
4. 业务场景示例:数据转换管道
;; 数据处理管道
(use-modules (srfi srfi-1)
(ice-9 regex)
(json))
(define (process-log-lines lines)
"处理日志行,提取错误信息并统计"
(let* ((error-lines (filter
(lambda (line)
(string-contains line "ERROR"))
lines))
(parsed (map
(lambda (line)
(let ((m (string-match
"\\[(.+?)\\] ERROR (.+)" line)))
(if m
`((time . ,(match:substring m 1))
(message . ,(match:substring m 2)))
#f)))
error-lines))
(valid (filter identity parsed)))
`((total-errors . ,(length valid))
(errors . ,valid))))
1.5.2 Guile 的优势
| 优势 | 详细说明 |
|---|---|
| 完全自由 | GNU GPL 许可证,无商业限制 |
| 标准兼容 | 兼容 R5RS/R7RS,代码可移植 |
| C 集成 | 一流的 C FFI,嵌入简单 |
| 模块系统 | 强大的命名空间管理 |
| 并发支持 | 绿色线程、CPS 引擎 |
| 活跃社区 | GNU 核心项目,持续维护 |
| Guix 生态 | 与 GNU Guix 深度集成 |
1.5.3 Guile 的局限
| 局限 | 说明 |
|---|---|
| 生态规模 | 相比 Python/JavaScript,库较少 |
| 数值性能 | 对于密集计算,不如 C/Rust |
| 学习曲线 | S-表达式对新手有一定门槛 |
| 社区规模 | 相比主流语言社区较小 |
| GUI 支持 | 原生 GUI 库选择有限 |
1.6 Guile 版本选择
截至 2026 年,Guile 的版本状况:
| 版本 | 状态 | 建议 |
|---|---|---|
| Guile 2.2 | 维护模式 | 旧项目兼容 |
| Guile 3.0 | 稳定版 | 推荐使用 |
| Guile 4.0 | 开发中 | 关注但不用于生产 |
# 检查 Guile 版本
guile --version
# GNU Guile 3.0.9
# Copyright (C) 1995-2024 Free Software Foundation, Inc.
1.7 本章小结
| 要点 | 说明 |
|---|---|
| Guile 是什么 | GNU 官方扩展语言,基于 Scheme |
| 核心标准 | R5RS 为基础,吸收 R6RS/R7RS 优点 |
| GNU 扩展 | 模块系统、SRFI、网络、进程管理 |
| 与 CL 对比 | 更简洁、更纯粹,但生态较小 |
| 适用场景 | GNU 工具扩展、脚本、配置、嵌入 |
扩展阅读
- Guile 官方手册 - Introduction
- Scheme 标准文档
- SRFI 索引
- SICP 中文版
- Practical Common Lisp — 了解 Common Lisp 思维方式
下一章:第 2 章:安装与环境搭建