为什么朱莉娅没有关闭复制数组呢?

Sam*_*art 1 julia

刚刚在我的程序中发现了一个令人讨厌的错误,因为Julia在定义闭包时没有复制数组.这使得继续编程变得困难.这种设计选择的动机是什么?

有关将闭包状态与程序状态分离的建议吗?

举个例子

l = [2 1; 0 0];
f = x -> l[2,2];
Run Code Online (Sandbox Code Playgroud)

然后f(1)= 0,但如果改变l [2,2] = 1,则f(1)= 1.

Tas*_*nou 6

你认为这是一个"封闭"并不成立.l在此时匿名函数的上下文中不是"闭合"变量.它只是对从"外部"范围继承的变量的引用(因为它尚未在匿名函数内部重新定义).

这是一个真正的闭包的例子:

f = let l=[2 1;0 0]
  x -> l[2,2];
end
Run Code Online (Sandbox Code Playgroud)

该变量l现在是let块的本地变量,而不是全局范围.f仍然可以访问它,即使它在技术上超出了范围.这就是封闭意味着什么.

由于l超出范围,它不再可访问,除非通过f它可以访问它作为封闭变量.


PS.我将在这里走出困境并假设你所期待的是类似matlab的行为.与matlab的最大区别在于,当您在那里定义匿名函数句柄时,它通过复制所有变量并使它们成为函数"对象"的一部分来捕获工作空间的当前状态.您可以使用该functions命令进行确认.Matlab没有与julia相同的参考.这是julia的优势,而不是弱点,因为它允许用户利用避免重新分配内存的优化,这在matlab*中更难实现.

*虽然公平,但matlab以其他方式闪耀,试图为您优化这一点


编辑: Liso在评论中指出了一个非常重要的陷阱.假设l已经存在于全局工作空间中,我们输入

let l=l
Run Code Online (Sandbox Code Playgroud)

虽然这是完全有效的语法,llet块创建一个局部变量,但它仍然只是作为对全局的引用而初始化l.因此,对全局的任何更改l仍会影响闭包,这不是您想要的.在这种情况下,您应该尝试通过制作副本(或深层副本,取决于您的用例)来"模仿"matlab行为,这样一旦局部变量超出范围并成为局部变量就真正独立于其他任何东西. '关闭'即

let l = deepcopy(l)
Run Code Online (Sandbox Code Playgroud)

另外,为了完整性,当一个人在julia中关闭时,值得指出这是如何在引擎盖下实现的:你的结果f函数只是一个可调用的对象,包含一个字段,用于每个需要注意的"封闭"变量; 你甚至可以访问它f.l.