Особенности использования и внутренней работы функций * Set *

Я только что заметил одну недокументированную особенность внутренней работы * 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}

What в чем причина такой разницы? Почему 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); а [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)

Мы можем увидеть, что происходит внутри новых версий Mathematica , когда мы оцениваем a: = (a = .; 5); a [b] = 2 :

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 для таких операций?


Тодд Гейли (Wolfram Research) объяснил такое поведение:

Вначале позвольте мне указать, что в 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)

Мы можем увидеть, что происходит внутри новых версий Mathematica , когда мы оцениваем a: = (a = .; 5); a [b] = 2 :

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 для таких операций?


Тодд Гейли (Wolfram Research) объяснил такое поведение:

Вначале позвольте мне указать, что в 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)

Мы можем увидеть, что происходит внутри новых версий Mathematica , когда мы вычисляем a: = (a = .; 5); a [b] = 2 :

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 для таких операций?


Тодд Гейли (Wolfram Research) объяснил такое поведение:

Вначале позвольте мне указать, что в

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 для таких операций?


Тодд Гейли (Wolfram Research) объяснил такое поведение:

Вначале позвольте мне указать, что в

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 для таких операций?


Тодд Гейли (Wolfram Research) объяснил такое поведение:

Вначале позвольте мне указать, что в Mathematica 8, J / Link больше не набор перегрузок. Внутреннее ядро был создан механизм, который среди другие вещи, позволяет J / Link избегать потребность в специальных "трюках" с Set.

J / Link перегрузил Set из в самом начале, почти двенадцать лет тому назад. Это позволяет поддерживать это синтаксис для присвоения значения Java поле:

  javaObject @ field = значение

Перегруженное определение Set вызывает замедление выполнения заданий форма

  _Symbol [_Symbol] = значение

Конечно, задание - это быстро операции, поэтому замедление небольшое в реальные сроки. Только узкоспециализированный типы программ, вероятно, будут существенно повлиял.

Перегрузка Set не , а не вызывает звонить в Java по заданиям, которые не задействовать объекты Java (это будет очень дорого). Это можно проверить с простым использованием TracePrint на ваш a [b] = c.

Он, как вы заметили, слегка изменение поведения заданий которые соответствуют _Symbol [_Symbol] = value. В частности, в f [_Symbol] = value, f оценивается дважды. Это может вызвать проблемы для кода со следующими (очень необычная) форма:

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

Я не могу припомнить, чтобы когда-либо видел "настоящие" код вроде этого или обнаружение проблемы

Я хочу удалить все символы между всеми парами скобок и сохранить в новой строке, например: new_string = AX&E

Я попытался сделать это:

p = re.compile("\(.*?\)", re.DOTALL)
new_string = p.sub("", s)

Это дает результат: AX & EUr)

Есть ли способ исправить это, вместо того чтобы повторять каждый элемент в строке?

6
задан Adam Lear 1 May 2011 в 06:13
поделиться