闭包 #

一、闭包概念 #

1.1 什么是闭包 #

闭包是一个函数,它可以捕获并访问其外部作用域中的变量。

julia
function outer()
    x = 10
    function inner()
        x + 1
    end
    return inner
end

f = outer()
f()

1.2 变量捕获 #

闭包捕获的是变量本身,而不是变量的值:

julia
function make_counter()
    count = 0
    () -> (count += 1)
end

counter = make_counter()
counter()
counter()
counter()

二、闭包应用 #

2.1 计数器 #

julia
function make_counter(start=0)
    count = start
    () -> (count += 1)
end

counter = make_counter()
counter()
counter()

counter2 = make_counter(100)
counter2()

2.2 累加器 #

julia
function make_accumulator(initial=0)
    total = initial
    x -> (total += x)
end

acc = make_accumulator()
acc(10)
acc(5)
acc(3)

2.3 乘法器工厂 #

julia
function make_multiplier(n)
    x -> x * n
end

times_3 = make_multiplier(3)
times_5 = make_multiplier(5)

times_3(10)
times_5(10)

2.4 配置函数 #

julia
function make_greeter(greeting, punctuation="!")
    name -> println("$greeting, $name$punctuation")
end

say_hello = make_greeter("Hello")
say_hi = make_greeter("Hi", "?")

say_hello("Julia")
say_hi("Julia")

三、闭包与状态 #

3.1 私有状态 #

闭包可以创建私有状态:

julia
function make_bank_account(initial=0)
    balance = initial
    
    (operation, amount=0) -> begin
        if operation == :deposit
            balance += amount
        elseif operation == :withdraw
            if amount <= balance
                balance -= amount
            else
                return "Insufficient funds"
            end
        elseif operation == :balance
            return balance
        else
            return "Unknown operation"
        end
        return balance
    end
end

account = make_bank_account(100)
account(:deposit, 50)
account(:withdraw, 30)
account(:balance)

3.2 多函数状态共享 #

julia
function make_counter_with_methods()
    count = 0
    
    (
        increment = () -> (count += 1),
        decrement = () -> (count -= 1),
        get = () -> count,
        reset = () -> (count = 0)
    )
end

counter = make_counter_with_methods()
counter.increment()
counter.increment()
counter.get()
counter.decrement()
counter.get()
counter.reset()
counter.get()

四、闭包与循环 #

4.1 循环中的闭包 #

julia
functions = []
for i in 1:3
    push!(functions, () -> i)
end

for f in functions
    println(f())
end

4.2 捕获问题 #

julia
functions = []
for i in 1:3
    push!(functions, let i = i
        () -> i
    end)
end

for f in functions
    println(f())
end

4.3 使用let创建新作用域 #

julia
function make_functions()
    functions = []
    for i in 1:3
        let i = i
            push!(functions, () -> i)
        end
    end
    return functions
end

funcs = make_functions()
[f() for f in funcs]

五、闭包与性能 #

5.1 类型稳定性 #

闭包捕获的变量可能导致类型不稳定:

julia
function make_adder_unstable()
    x = 0
    y -> begin
        x = y
        x + 1
    end
end

5.2 类型注解 #

使用类型注解提高性能:

julia
function make_adder_stable()
    x::Int = 0
    y::Int -> begin
        x = y
        x + 1
    end
end

六、实践练习 #

6.1 练习1:缓存函数 #

julia
function memoize(f)
    cache = Dict{Tuple, Any}()
    function(args...)
        key = args
        if !haskey(cache, key)
            cache[key] = f(args...)
        end
        return cache[key]
    end
end

fib = memoize(function(n)
    n <= 1 ? n : fib(n-1) + fib(n-2)
end)

fib(40)

6.2 练习2:节流函数 #

julia
function throttle(f, interval)
    last_called = Ref(time() - interval)
    function(args...)
        current = time()
        if current - last_called[] >= interval
            last_called[] = current
            return f(args...)
        end
        return nothing
    end
end

throttled_print = throttle(println, 1.0)
throttled_print("Hello")
throttled_print("World")
sleep(1.0)
throttled_print("Julia")

6.3 练习3:事件发射器 #

julia
function make_emitter()
    listeners = []
    
    (
        on = (callback) -> push!(listeners, callback),
        emit = (event) -> foreach(f -> f(event), listeners),
        off = (callback) -> filter!(f -> f !== callback, listeners)
    )
end

emitter = make_emitter()
emitter.on(x -> println("Listener 1: $x"))
emitter.on(x -> println("Listener 2: $x"))
emitter.emit("Hello")

6.4 练习4:状态机 #

julia
function make_state_machine(initial_state, transitions)
    state = Ref(initial_state)
    
    function transition(event)
        current = state[]
        if haskey(transitions, (current, event))
            state[] = transitions[(current, event)]
            return state[]
        end
        return nothing
    end
    
    () -> state[]
end

transitions = Dict(
    (:off, :switch) => :on,
    (:on, :switch) => :off
)

light = make_state_machine(:off, transitions)
light()

七、总结 #

本章我们学习了:

  1. 闭包概念:捕获外部变量
  2. 闭包应用:计数器、累加器、工厂函数
  3. 状态管理:私有状态和多函数共享
  4. 循环闭包:let块解决捕获问题
  5. 性能考虑:类型稳定性

接下来让我们学习Julia的类型系统!

最后更新:2026-03-27