第 1 部分 · Racket 核心
函数与过程
函数与过程
学习如何定义和使用函数,掌握高阶函数、lambda 表达式等核心概念。
定义函数
使用 define 定义命名函数:
#lang racket
;; 基本函数定义
(define (greet name)
(string-append "Hello, " name "!"))
(greet "Racket") ; => "Hello, Racket!"
;; 多参数函数
(define (add x y)
(+ x y))
(add 3 4) ; => 7
Lambda 表达式
匿名函数是函数式编程的核心:
;; lambda 定义匿名函数
(lambda (x) (* x x))
;; 直接使用
((lambda (x) (* x x)) 5) ; => 25
;; 绑定到变量
(define square (lambda (x) (* x x)))
(square 5) ; => 25
;; 简化语法
(define (square x) (* x x)) ; 等价于上面的定义
高阶函数
函数可以接受函数作为参数,或返回函数:
;; 接受函数作为参数
(define (apply-twice f x)
(f (f x)))
(apply-twice square 3) ; => 81 (3^2=9, 9^2=81)
;; 返回函数
(define (make-adder n)
(lambda (x) (+ x n)))
(define add5 (make-adder 5))
(add5 10) ; => 15
常用高阶函数
;; map - 映射
(map square '(1 2 3 4 5)) ; => '(1 4 9 16 25)
;; filter - 过滤
(filter even? '(1 2 3 4 5 6)) ; => '(2 4 6)
;; foldl / foldr - 归约
(foldl + 0 '(1 2 3 4 5)) ; => 15
(foldl cons '() '(1 2 3)) ; => '(3 2 1)
(foldr cons '() '(1 2 3)) ; => '(1 2 3)
;; andmap / ormap
(andmap positive? '(1 2 3)) ; => #t
(ormap even? '(1 3 5 7 8)) ; => #t
闭包
函数可以"记住"其定义时的环境:
(define (make-counter)
(let ([count 0])
(lambda ()
(set! count (+ count 1))
count)))
(define c1 (make-counter))
(define c2 (make-counter))
(c1) ; => 1
(c1) ; => 2
(c2) ; => 1 (独立的计数器)
(c1) ; => 3
递归
递归是 Racket 中处理循环的主要方式:
;; 简单递归
(define (factorial n)
(if (= n 0)
1
(* n (factorial (- n 1)))))
(factorial 5) ; => 120
;; 尾递归(优化为循环)
(define (factorial-tail n)
(let loop ([acc 1] [i n])
(if (= i 0)
acc
(loop (* acc i) (- i 1)))))
(factorial-tail 5) ; => 120
;; 处理列表
(define (sum lst)
(if (null? lst)
0
(+ (car lst) (sum (cdr lst)))))
(sum '(1 2 3 4 5)) ; => 15
函数组合
;; compose - 函数组合
(define (compose f g)
(lambda (x) (f (g x))))
(define add1-then-square
(compose square add1))
(add1-then-square 4) ; => 25 (4+1=5, 5^2=25)
;; 使用内置的 compose
((compose string-length symbol->string) 'hello) ; => 5
小结
函数是 Racket 中的"一等公民",这意味着你可以:
- 将函数作为参数传递
- 从函数中返回函数
- 将函数存储在数据结构中
- 在运行时动态创建函数
这种灵活性使得 Racket 能够表达非常抽象的编程模式。