在表达式中通过引用传递表达式

dal*_*lum 4 metaprogramming julia

我对朱莉娅来说相当新,所以对我可能有的语言的任何误解表示道歉.我最近大部分时间都在使用Python,并且大量使用了SymPy及其代码生成功能,而且似乎Julia的元编程功能是为了完全按我喜欢的方式编写代码而构建的.

特别是,我想在一组较小的构建块中构建Julia中的块矩阵,其间有一些不同的操作.出于调试目的,并且因为各种中间矩阵用于其他计算,我想将它们保存为包含变量的表达式,这样我就可以快速循环并测试不同的不同输入,而无需将所有内容包装在函数中.

现在,最小的案例研究中,说我有两个表达式mat1 = :amat2 = :b我想结合起来,形成一个新的,第三个表达式:

mat3 = :($mat1 + $mat2)
Run Code Online (Sandbox Code Playgroud)

以上方法工作得很好,直到我修改mat1mat2,在这种情况下,我不得不重新评估mat3,以反映此更新.我认为,这是因为$mat1 + $mat2没有通过mat1mat2引用,而是在评估该行时内插表达式.我想实现的行为是mat1mat2不被插入,直到我打电话eval(mat3),最好用最少的样板.

是否有可能以方便的语法实现这一目标?

Fen*_*ang 9

mat3将反映突变mat1mat2,而不是重新绑定mat1mat2.了解突变和重新绑定之间的区别非常重要.

突变

当修改对象的数据时发生突变.请注意,这不会影响任何名称,只会影响对象.这可以通过多种方式表现出来,包括push!具有复杂左侧的函数和赋值语法等A[1] = 5.

例如,以下所有都是变异的例子:

A = [1, 2, 3]
A[1] = 4
Run Code Online (Sandbox Code Playgroud)

名字A没有变化; A仍然指向同一个对象.的对象A表示被修改.

A = :(f(x))
A.args[1] = :g
Run Code Online (Sandbox Code Playgroud)

名字A没有变化; A仍然指向同一个对象.的对象A表示被修改.

mat1 = :(f(x))
mat2 = :(f(y))
mat3 = :($mat1 + $mat2)
mat1.args[1] = :g
Run Code Online (Sandbox Code Playgroud)

名字mat1没有变化; 它仍然指向同一个对象.该对象已被修改.mat3同样引用同一个对象,并且因为它已被修改,它将反映更改.的确,现在mat3包含:(g(x) + f(y)).

重新绑定

(也称为作业)

没有修改对象数据但名称的目标更改为其他对象的目标时,会发生重新绑定.这由一个简单的=任务表示,左侧是反弹的东西.

x = 2
x = 3
Run Code Online (Sandbox Code Playgroud)

x是从物体2到物体的反弹3.我们没有改变对象2.实际上,因为2是一个不可变对象,所以不允许改变对象2.相反,可观察值的x变化是因为它现在引用了一个不同的对象:3.

A = [1, 2, 3]
A = [4, 2, 3]
Run Code Online (Sandbox Code Playgroud)

再一次,我们不是在改变载体A; 我们正在创建一个新的向量,现在A引用这个新的向量.区分突变和重​​新绑定很重要.同样,变异作用于对象,重新绑定作用于名称.

mat1 = :x
mat2 = :y
mat3 = :($mat1 + $mat2)
mat1 = :z
Run Code Online (Sandbox Code Playgroud)

在此,简单的分配不会发生变异的对象:xmat1引用; 它只是重新绑定mat1到不同的对象:z.这意味着mat3包含该对象的:x内容不会受到影响.

请注意,这Symbol是一个不可变类型,因此您无法改变它.因此,不可能做你提出的建议.

做你提议的更好的方法是使用函数而不是单个表达式.可以多次调用函数,生成不同的对象.

mat1 = :x
mat2 = :y
mat3() = :($mat1 + $mat2)  # function definition
mat3()  # :(x + y)
mat1 = :z
mat3()  # :(z + y)
Run Code Online (Sandbox Code Playgroud)