title: CS107-第30讲-Scheme函数定义 source: Stanford CS107 Programming Paradigms original_path: /田浩然上传的资料/电子书/ProgrammingParadigms/materials/icsppcs107/30-Scheme-Functions.pdf author: Jerry Cain, Ben Newman, David Hall size: 99KB pages: 11 date_processed: 2026-09-30 method: PDF文本提取 status: done
Scheme函数定义 - Stanford CS107讲义
核心主题
本讲义介绍Scheme编程语言中函数定义的基本语法和递归编程模式。
关键概念
1. define特殊形式
(define (procedure-name <arguments>)
<expression to evaluate>)示例:摄氏转华氏温度函数
(define (celsius->fahrenheit celsius)
(+ (* 1.8 celsius) 32))2. 谓词函数命名约定
返回布尔值的函数名以?结尾,如:
leap-year?- 判断闰年zero?- 判断是否为零
3. 递归是Scheme的核心
Scheme的核心数据结构是列表(list),列表通过归纳定义,因此递归是自然的选择。
尾递归优化:所有Scheme解释器都能将尾递归转换为迭代等价形式。
4. 典型递归示例
阶乘函数
(define (factorial n)
(if (zero? n) 1
(* n (factorial (- n 1)))))注意:Scheme支持任意大整数。
斐波那契函数
(define (fibonacci n)
(if (< n 2) n
(+ (fibonacci (- n 1))
(fibonacci (- n 2)))))传统实现效率低(指数级递归调用)。
5. 快速斐波那契(动态规划)
(define (fast-fibonacci n)
(fast-fibonacci-helper n 0 1))
(define (fast-fibonacci-helper n base-0 base-1)
(cond ((zero? n) base-0)
((zero? (- n 1)) base-1)
(else (fast-fibonacci-helper (- n 1) base-1 (+ base-0 base-1)))))线性递归而非二叉递归,速度与阶乘相当。
6. car-cdr递归模式
处理列表的标准模式:
(define (sum ls)
(if (null? ls) 0
(+ (car ls) (sum (cdr ls)))))三重列表函数
(define (triple-everything numbers)
(if (null? numbers) '()
(cons (* 3 (car numbers))
(triple-everything (cdr numbers)))))字符串部分连接
(define (generate-concatenations strings)
(generate-concatenations-using strings ""))
(define (generate-concatenations-using strings accum)
(if (null? strings) '()
(cons (string-append accum (car strings))
(generate-concatenations-using (cdr strings)
(string-append accum (car strings))))))7. let绑定
用于避免重复计算子表达式:
(define (pwr base exponent)
(if (zero? exponent) 1
(let ((root (pwr base (quotient exponent 2))))
(if (zero? (remainder exponent 2))
(* root root)
(* root root base)))))let语法结构
(let ((<name-1> <expression-1>)
(<name-2> <expression-2>)
...)
<expression using names 1 through k>)注意:let绑定的计算顺序不保证,因此<expression-2>不能使用<name-1>。
8. flatten函数
将任意嵌套列表展平为单层列表:
(define (flatten sequence)
(cond ((null? sequence) '())
((list? (car sequence))
(append (flatten (car sequence))
(flatten (cdr sequence))))
(else (cons (car sequence)
(flatten (cdr sequence))))))9. 快排实现
分区函数
(define (partition pivot num-list)
(if (null? num-list) '(() ())
(let ((split-of-rest (partition pivot (cdr num-list))))
(if (< (car num-list) pivot)
(list (cons (car num-list) (car split-of-rest))
(cadr split-of-rest))
(list (car split-of-rest)
(cons (car num-list) (car (cdr split-of-rest))))))))快排函数
(define (quicksort num-list)
(if (<= (length num-list) 1) num-list
(let ((split (partition (car num-list) (cdr num-list))))
(append (quicksort (car split))
(list (car num-list))
(quicksort (cadr split))))))实践要点
- 函数文件扩展名:惯例使用
.scm - 加载文件:使用
(load "filename.scm") - 纯函数式风格:避免副作用,函数组合是核心范式
- 列表操作:
car取首元素,cdr取剩余列表,cons构建列表,null?判断空列表
知识关联
- 与C程序设计语言-第11章-运算符重载对比:Scheme的函数式范式 vs C的面向对象范式
- 与Python高级编程-函数式工具形成对照:Lisp家族与函数式编程的现代实践