gpt4 book ai didi

wolfram-mathematica - *Set*函数的使用和内部工作细节

转载 作者:行者123 更新时间:2023-12-04 08:03:55 26 4
gpt4 key购买 nike

我刚刚注意到 *Set* 内部工作的一个未记录的功能Mathematica 中的函数。

考虑:

In[1]:= a := (Print["!"]; a =.; 5);
a[b] = 2;
DownValues[a]

During evaluation of In[1]:= !

Out[3]= {HoldPattern[a[b]] :> 2}


In[4]:= a := (Print["!"]; a =.; 5);
a[1] = 2;
DownValues[a]

During evaluation of In[4]:= !

During evaluation of In[4]:= Set::write: Tag Integer in 5[1] is Protected. >>

Out[6]= {HoldPattern[a[b]] :> 2}

这种差异的原因是什么?为什么 a尽管 Set 被评估有属性 HoldFirst ?这种行为对哪些目的有用?

还要注意这种情况:
In[7]:= a := (Print["!"]; a =.; 5)
a[b] ^= 2
UpValues[b]
a[b]

During evaluation of In[7]:= !

Out[8]= 2

Out[9]= {HoldPattern[5[b]] :> 2}

Out[10]= 2

如您所见,我们得到了 5[b] 的工作定义。避免 Protected标签属性 Integer通常情况下会导致错误:
In[13]:= 5[b] = 1

During evaluation of In[13]:= Set::write: Tag Integer in 5[b] is Protected. >>

Out[13]= 1

避免此错误的另一种方法是使用 TagSet* :
In[15]:= b /: 5[b] = 1
UpValues[b]

Out[15]= 1

Out[16]= {HoldPattern[5[b]] :> 1}

为什么会有这些特点?

关于我的问题,为什么我们可以写 a := (a =.; 5); a[b] = 2虽然不能 a := (a =.; 5); a[1] = 2 .在真正的 Mathematica 5 中我们不能写 a := (a =.; 5); a[b] = 2也:
In[1]:=
a:=(a=.;5);a[b]=2
From In[1]:= Set::write: Tag Integer in 5[b] is Protected. More...
Out[1]=
2

(以上是从 Mathematica 5.2 复制的)

当我们评估 a := (a =.; 5); a[b] = 2 时,我们可以看到在新版本的 Mathematica 内部发生了什么。 :
In[1]:= a:=(a=.;5);
Trace[a[b]=2,TraceOriginal->True]
Out[2]= {a[b]=2,{Set},{2},a[b]=2,{With[{JLink`Private`obj$=a},RuleCondition[$ConditionHold[$ConditionHold[JLink`CallJava`Private`setField[JLink`Private`obj$[b],2]]],Head[JLink`Private`obj$]===Symbol&&StringMatchQ[Context[JLink`Private`obj$],JLink`Objects`*]]],{With},With[{JLink`Private`obj$=a},RuleCondition[$ConditionHold[$ConditionHold[JLink`CallJava`Private`setField[JLink`Private`obj$[b],2]]],Head[JLink`Private`obj$]===Symbol&&StringMatchQ[Context[JLink`Private`obj$],JLink`Objects`*]]],{a,a=.;5,{CompoundExpression},a=.;5,{a=.,{Unset},a=.,Null},{5},5},RuleCondition[$ConditionHold[$ConditionHold[JLink`CallJava`Private`setField[5[b],2]]],Head[5]===Symbol&&StringMatchQ[Context[5],JLink`Objects`*]],{RuleCondition},{Head[5]===Symbol&&StringMatchQ[Context[5],JLink`Objects`*],{And},Head[5]===Symbol&&StringMatchQ[Context[5],JLink`Objects`*],{Head[5]===Symbol,{SameQ},{Head[5],{Head},{5},Head[5],Integer},{Symbol},Integer===Symbol,False},False},RuleCondition[$ConditionHold[$ConditionHold[JLink`CallJava`Private`setField[5[b],2]]],False],Fail},a[b]=2,{a[b],{a},{b},a[b]},2}

我很惊讶地看到在像为变量赋值这样的纯语言相关操作中调用 Java。将 Java 用于此类操作是否合理?

Todd Gayley(Wolfram 研究) has explained这种行为:

At the start, let me point out that in Mathematica 8, J/Link no longer overloads Set. An internal kernel mechanism was created that, among other things, allows J/Link to avoid the need for special, er, "tricks" with Set.

J/Link has overloaded Set from the very beginning, almost twelve years ago. This allows it support this syntax for assigning a value to a Java field:

 javaObject@field = value

The overloaded definition of Set causes a slowdown in assignments of the form

 _Symbol[_Symbol] = value

Of course, assignment is a fast operation, so the slowdown is small in real terms. Only highly specialized types of programs are likely to be significantly affected.

The Set overload does not cause a call to Java on assignments that do not involve Java objects (this would be very costly). This can be verified with a simple use of TracePrint on your a[b]=c.

It does, as you note, make a slight change in the behavior of assignments that match _Symbol[_Symbol] = value. Specifically, in f[_Symbol] = value, f gets evaluated twice. This can cause problems for code with the following (highly unusual) form:

 f := SomeProgramWithSideEffects[]
f[x] = 42

I cannot recall ever seeing "real" code like this, or seeing a problem reported by a user.

This is all moot now in 8.0.

最佳答案

UpSet为例首先,这是预期的行为。一个人可以写:

 5[b] ^= 1

分配给 b不是整数 5 .

关于 SetSetDelayed ,虽然它们具有 Hold 属性,但它们仍然在内部评估表达式。这允许诸如:
p = n : (_List | _Integer | All);

f[p] := g[n]

测试:
f[25]
f[{0.1, 0.2, 0.3}]
f[All]
   g[25]
   g[{0.1, 0.2, 0.3}]
   g[All]

One can see that heads area also evaluated. This is useful at least for UpSet:

p2 = head : (ff | gg);
p2[x] ^:= Print["Echo ", head];

ff[x]
gg[x]

Echo ff

Echo gg



很容易看出, Set 也会发生这种情况。 ,但我不太清楚这会有什么用处:
j = k;
j[5] = 3;
DownValues[k]

(* Out= {HoldPattern[k[5]] :> 3} *)

我对你问题第一部分的分析是错误的。我现在不明白为什么 a[b] = 2被接受并 a[1] = 2不是。也许在分配的某个阶段,第二个出现为 5[1] = 2并且模式检查引发错误,因为 LHS 上没有符号。

关于wolfram-mathematica - *Set*函数的使用和内部工作细节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5846756/

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