我正在学习Elixir,我刚刚开始学习闭包的部分。当一种语言有闭包时,我通常要做的第一件事就是尝试创建闭包算法。在JavaScript中,它看起来像这样:
let counter = function() {
let count = 0;
return function() {
count += 1;
return count;
};
}();
字符串
然后,每次调用counter
时,它将按顺序返回一个新的数字。
counter(); // returns 1
counter(); // returns 2
counter(); // returns 3
counter(); // etc.
型
有没有可能在Elixir中实现这个?主要的问题似乎是count
在Elixir中是不可变的。我可以把它变成一个单元素列表,但这听起来像是一个坏主意。Elixir如何处理这种纯粹假设的情况?
2条答案
按热度按时间n9vozmp41#
主要的问题似乎是
count
在Elixir中是不可变的。字符串
在elixir中,值是不可变的,但是变量可以指向内存中存储其他值的不同位置。例如,当行
count = 2
执行时,2被存储在内存中的某个位置,然后count
被绑定到新的内存位置。之后,没有变量被绑定到1的内存位置,这样内存就可以进行垃圾收集了。Elixir有闭包,因为函数确实带有定义该函数的环境中的绑定,但是绑定到特定的内存位置,并且这些内存位置的值是不可变的:
型
在iex中:
型
我可以把它做成一个单元素列表,但这听起来像是一个坏主意。
......但它不会起作用。列表是内存中不可变值的优势的一个例子。当你在列表的头部添加一个值时,elixer会在内存中的其他位置创建一个全新的列表。但是,elixer知道,旧列表是不可变的,而不是将旧列表复制到新列表的内存位置。因此elixir可以只使用指向旧列表的指针。新的内存位置由列表的新元素加上指向旧列表的指针组成--不需要复制。在闭包的情况下,绑定将指向内存中原始列表的位置,并且从原始列表创建的任何新列表将驻留在存储器中的其它地方。
Elixir 会用什么方法来处理这种纯粹假设的情况?
在elixir/erlang中,可以使用GenServer来保存函数调用之间的状态:
型
当你写:
型
elixir查找一个名为
handle_call()
的回调函数,该函数的第一个参数与:increment
相匹配,并执行该函数,将状态作为第三个参数传入。您可以定义handle_call()
来执行您想要的操作,然后将回复发送回调用进程并设置新的状态。在iex中:
型
bmvo0sr52#
如果你需要状态,使用process。在Elixir中,惯用的方法是使用Agent和GenServer。
代理文档中的示例完全按照您的要求执行:
字符串
使用方法:
型