Julia 为什么不';复制数组吗?

Julia 为什么不';复制数组吗?,julia,Julia,刚刚在我的程序中发现了一个令人讨厌的错误,因为Julia在定义闭包时不复制数组。这使得继续编程变得困难。这种设计选择的动机是什么 有没有关于将我的闭包状态与程序状态分离的建议 例如 l = [2 1; 0 0]; f = x -> l[2,2]; 那么f(1)=0,但是如果你改变l[2,2]=1,那么f(1)=1 你认为这是一个“终结”的假设不成立l不是一个“闭合”变量。它只是对从“外部”作用域继承的变量的引用(因为它没有在匿名函数中被本地重新定义) 下面是一个真正的闭包示例: 变量l现

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

有没有关于将我的闭包状态与程序状态分离的建议

例如

l = [2 1; 0 0];
f = x -> l[2,2];

那么f(1)=0,但是如果你改变l[2,2]=1,那么f(1)=1

你认为这是一个“终结”的假设不成立<此时,在匿名函数的上下文中,code>l不是一个“闭合”变量。它只是对从“外部”作用域继承的变量的引用(因为它没有在匿名函数中被本地重新定义)

下面是一个真正的闭包示例:

变量
l
现在是
let
块的局部变量,不在全局范围内
f
仍然可以访问它,即使它在技术上已经超出了范围。这就是闭包的意思

由于
l
已超出范围,它不再可访问,除非通过
f
进行访问,这是一个闭包,可以作为闭合变量访问它


顺便说一句,我要冒险一试,假设你们所期望的是类似matlab的行为。与matlab的最大区别在于,当您在此处定义匿名函数句柄时,它通过复制所有变量,并使其成为函数“对象”的一部分,来捕获工作区的当前状态。您可以使用
函数
命令确认这一点。Matlab没有与julia相同的引用方式。这是julia的优点,而不是缺点,因为它允许用户使用优化来避免内存的重新分配,这在matlab*中很难实现

*尽管公平地说,matlab在其他方面也很出色,它试图为您优化这一点


编辑:Liso指出了评论中一个非常重要的陷阱。假设全局工作区中已存在
l
,然后键入

let l=l
虽然这是非常有效的语法,使
l
成为
let
块的局部变量,但这仍然只是初始化为对全局
l
的引用。因此,对全局
l
的任何更改仍将影响闭包,这不是您想要的。在这种情况下,您应该尝试通过复制(或深度复制,取决于您的用例)来“模拟”matlab行为,这样,一旦局部变量超出范围并变得“关闭”,即

let l = deepcopy(l)

此外,为了完整性,在julia中进行闭包时,值得指出这是如何在后台实现的:生成的
f
函数只是一个可调用的对象,包含每个需要注意的“已关闭”变量的字段;您甚至可以通过
f.l

const l2=copy(l)访问此文件;f=x->l2[2,2]
?我很好奇-你来自哪种语言,你会期待这种行为?@MichaelK.Borregaard
deepcopy
在某些情况下(例如数组数组),而不是
copy
.true--15 chars但是Tasos的答案是正确的。如果您已经定义了l,并且想要使用
let l=l
,那么您可能想要通过
let l=deepcopy(l)
复制整个变量,对不起,我希望它不会显得太迂腐。但我认为最好从对初学者的适当描述开始。如果
让l=l
本地l不引用全局l。局部l是全局l的副本,两者都是对同一结构(此处为数组)的(不同)引用。如果我们通过
l=something
改变全局l,它不会影响局部l(并且结构到局部l是绑定的)。这只是因为全局l绑定到其他值。但如果我们这样做,例如
l[1]=something
,那么我们正在修改ls(全局和局部)都绑定到的结构。这就是为什么我们需要在这里进行(深度)复制。@Liso我很欣赏你所说的,julia中的变量通常最好被认为是内存中某个对象的“标签”,但我觉得试图解释这一点会涉及太多的深度,并且会造成更多的混乱,而不是帮助。最好保持简短(我已经在答案中添加了比我希望的更多的内容)。。。不过,谢谢你的评论,希望有足够感兴趣的人会关注这段对话,并决定了解更多有关这方面的信息!:)@TasosPapastylianou精彩的回答,感谢您的完整性。事实上,问题在于我是一名数学家(我在思考函数语言中的匿名函数)和一名Matlab用户;你猜对了。传递引用的速度更快,不是缺点,这是有道理的。再次感谢大家,非常有帮助。
let l = deepcopy(l)