gpt4 book ai didi

metaprogramming - 在表达式内部通过引用传递表达式

转载 作者:行者123 更新时间:2023-12-04 07:12:44 24 4
gpt4 key购买 nike

我对 Julia 很陌生,所以对于我可能对语言的任何误解,我深表歉意。我最近主要使用 Python,并大量使用 SymPy 及其代码生成功能,看起来 Julia 及其元编程功能是专为以我喜欢的风格编写代码而构建的。

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

现在,对于一个最小的案例研究,假设我有两个表达式 mat1 = :amat2 = :b我想组合形成一个新的第三个表达式:

mat3 = :($mat1 + $mat2)

在我修改 mat1 之前,上述方法可以正常工作和 mat2 ,在这种情况下,我必须重新评估 mat3为了反射(reflect)此更新。我想这是由 $mat1 + $mat2 引起的。没有通过 mat1mat2通过引用,而是在评估该行时在内部插入表达式。我想要实现的行为是 mat1mat2直到我调用 eval(mat3) 才插入,最好使用最少的样板。

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

最佳答案

mat3将反射(reflect) mat1 的突变和 mat2 ,但不重新绑定(bind) mat1mat2 .了解突变和重新结合之间的区别很重要。

突变

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

例如,以下所有内容都是突变的示例:

A = [1, 2, 3]
A[1] = 4

名称 A 不变; A 仍然指向同一个对象。 A 的对象代表被修改。
A = :(f(x))
A.args[1] = :g

名称 A 不变; A 仍然指向同一个对象。 A 的对象代表被修改。
mat1 = :(f(x))
mat2 = :(f(y))
mat3 = :($mat1 + $mat2)
mat1.args[1] = :g

姓名 mat1不变;它仍然指向同一个对象。该对象已修改。 mat3也引用同一个对象,并且因为它已被修改,它将反射(reflect)更改。确实,现在 mat3包含 :(g(x) + f(y)) .

重新绑定(bind)

(也称为分配)

当没有修改对象数据但名称的目标更改为不同对象的目标时,会发生重新绑定(bind)。这由一个简单的 = 表示。分配,左边是东西反弹。
x = 2
x = 3

这里 x正在从对象 2 反弹到对象 3 .我们不会更改对象 2 .事实上,因为 2是不可变对象(immutable对象),不允许改变对象 2 .相反, x 的可观察值的原因改变是因为它现在引用了一个不同的对象: 3 .
A = [1, 2, 3]
A = [4, 2, 3]

再一次,我们没有改变向量 A ;我们正在创建一个新向量,现在 A引用这个新向量。区分突变和重​​新结合很重要。再一次,变异作用于对象,重新绑定(bind)作用于名称。
mat1 = :x
mat2 = :y
mat3 = :($mat1 + $mat2)
mat1 = :z

注意这里的简单赋值不会改变对象 :x。那 mat1引用;它只是重新绑定(bind) mat1到不同的对象 :z .这意味着 mat3 ,其中包含对象 :x ,不会受到影响。

请注意 Symbol不可变 类型,所以你不能改变它。因此,不可能按照您的建议去做。

执行您建议的更好方法是使用函数而不是单个表达式。一个函数可以被多次调用,产生不同的对象。
mat1 = :x
mat2 = :y
mat3() = :($mat1 + $mat2) # function definition
mat3() # :(x + y)
mat1 = :z
mat3() # :(z + y)

关于metaprogramming - 在表达式内部通过引用传递表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44016401/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com