Engee 文档
Notebook

编程中的闭包。

闭包是一个函数,即使在外部函数完成执行后,它仍保留对其词法作用域变量的访问权限。 这在编程中是一个强大的概念,特别是在支持函数式编程的语言中。

在Julia的示例中,我们看到了一个经典的闭包实现。:

In [ ]:
function make_counter()
    count = 0  # Эта переменная «замыкается» внутри функции
    function counter()
        count += 1
        return count
    end
    return counter
end
Out[0]:
make_counter (generic function with 1 method)

这里 **make_counter**是创建并返回函数的工厂函数 counter. 内部功能 **counter**可以访问变量 **count**即使之后 **make_counter**完成其执行。

短路如何工作

  1. 变量捕获:当创建闭包时,它会"记住"其周围作用域中的所有变量。

  2. State:这些变量在闭包调用之间保留其状态。

  3. 隔离:每个新闭包都会创建自己的捕获变量副本。

在我们的例子中,每个调用都是 **make_counter()**使用自己的变量创建一个新的闭包 count:

In [ ]:
my_counter = make_counter()  # Создаем первое замыкание
println("my_counter: $my_counter")
another_counter = make_counter()  # Создаем второе независимое замыкание
println("another_counter: $another_counter")
my_counter: counter
another_counter: counter

要使用它,调用创建的计数器就足够了。

In [ ]:
println("my_counter первый вызов: $(my_counter())")  
println("my_counter второй вызов: $(my_counter())")  
println("Вызов another_counter: $(another_counter())")  
my_counter первый вызов: 1
my_counter второй вызов: 2
Вызов another_counter: 1

闭包的实际应用是,例如,私有变量的实现。

In [ ]:
function create_person(name)
    age = 0
    function get_name()
        return name
    end
    function get_age()
        return age
    end
    function have_birthday()
        age += 1
        return age
    end
    return (get_name=get_name, get_age=get_age, have_birthday=have_birthday)
end

person = create_person("Alice")
println(person.get_name())  # Alice
println(person.have_birthday())  # 1
Alice
1

或memoization(结果缓存)

In [ ]:
function make_cached(f)
    cache = Dict()
    function cached(x)
        if !haskey(cache, x)
            cache[x] = f(x)
        end
        return cache[x]
    end
    return cached
end

# Пример использования
expensive_computation(x) = (sleep(1); x^2)
cached_comp = make_cached(expensive_computation)

println(cached_comp(2))  # Вычисляется (занимает время)
println(cached_comp(2))  # Берется из кеша (мгновенно)
4
4

还可以创建具有预设参数的函数。

In [ ]:
function make_multiplier(factor)
    function multiplier(x)
        return x * factor
    end
    return multiplier
end

double = make_multiplier(2)
triple = make_multiplier(3)

println(double(5))  # 10
println(triple(5))  # 15
10
15

结论

总而言之,值得分析这种方法的利弊。
优势:

*封装和数据隐藏,

*创建有状态函数,

*创建专门功能的灵活性,

*支持函数式编程模式。

缺点:

*内存消耗(捕获的变量不释放),

*调试可能遇到的困难

最后,我想说闭包是一个强大的工具。 它们用于许多领域,从简单的计数器到复杂设计模式的实现。 理解闭包对于任何使用支持功能的语言的开发人员来说都很重要。

所给出的例子只展示了闭包的一小部分可能性。 通过对它们进行试验,您将能够找到越来越多的新方法来将此概念应用到您的项目中。