第 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 能够表达非常抽象的编程模式。