Почему я должен оценивать это дважды?

#wolfram-mathematica

#wolfram-mathematica

Вопрос:

Я не могу понять, почему я должен оценивать это дважды (в Mathematica 7) для выполнения задания.

Первая оценка:

 Unprotect[Rule];
Attributes[Rule]
pp = Plot | LogLinearPlot | ListPlot | ParametricPlot3D;
(h : pp)[True -> False] ^:= Print["Irrelevant data"]

(*

Out[2]= {SequenceHold}

During evaluation of In[1]:= UpSetDelayed::write: Tag Rule in (h:Plot|LogLinearPlot|ListPlot|ParametricPlot3D)[True->False] is Protected. >>

Out[4]= $Failed

*)
  

Как видно из Out[2]= {SequenceHold} , Unprotect[Rule] сработало, однако сообщение об ошибке указывает на обратное. Если я оцениваю ячейку во второй раз, присваивание выполняется и ошибка не генерируется.

Почему это происходит?

Ответ №1:

Как вы, возможно, хорошо знаете, Mathematica загружает двоичные файлы MX, которые реализуют некоторые из ее функциональных возможностей. В этих MX-файлах хранятся реализации, а также определения и атрибуты.

Это коварно, но ваш Unprotect[Rule] отменен недавно загруженным MX-файлом Mathematica, и это объясняет, почему это сработало во второй раз. Потому что Mathematica уже загрузила все необходимые MX-файлы.

Если вы сначала вычислите все символы в вашем выражении, то оно перестанет жаловаться:

 {Unprotect, Rule, Attributes, Plot, LogLinearPlot, ListPlot, 
  ParametricPlot3D, True, False, Print};
Unprotect[Rule];
Attributes[Rule];
pp = Plot | LogLinearPlot | ListPlot | ParametricPlot3D;
(h : pp)[True -> False] ^:= Print["Irrelevant data"]
  

РЕДАКТИРОВАТЬ Первая оценка необходима для запуска всей автоматической загрузки перед снятием защиты Rule .

Комментарии:

1. Позвольте мне посмотреть, понимаю ли я это. Mathematica загружает одну из функций Plot только тогда, когда она появляется (через DeclarePackage или что-то подобное) и этот пакет содержит Unprotect[Rule] ... Protect[Rule] пару (или что-то подобное). Правильно?

2. Не совсем, оно содержит атрибут символа. Что-то вроде SetAttributes[a, Protected]; DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "tmp.mx"}], a]; и затем Unprotect[a]; Get[FileNameJoin[{$HomeDirectory, "Desktop", "tmp.mx"}]]; a = 1 .

3. В этом случае виновником является, LogPlot.mx который загружается при вычислении символа LogLinearPlot . Почему это должно восстановить защищенный статус Rule для меня загадка. Возможно, в этом файле есть Unprotect[Rule];...;Protect[Rule] последовательность. Интересно, что LogLinearPlot не имеет обычного Stub атрибута, включенного DeclarePackage . Здесь должен работать какой-то другой механизм автоматической загрузки.

4. @Sasha Спасибо, что поделился этой информацией. С точки зрения пользователя, я бы все равно классифицировал это как ошибку — это противоречит самой общей семантике языка, касающейся защиты символов, а также документации. Как только объем стороннего mma-кода, используемого в рабочей среде, станет значительным (при условии, что это когда-либо произойдет), подобные случаи станут реальной проблемой. По крайней мере, IMO необходимы официальные рекомендации по кодированию со списком встроенных функций, которые никогда не должны быть изменены пользователем, т. Е. для которых такие модификации приведут к неопределенному поведению.

5. Загрузка файла @WReach .mx не работает через Stub . Добавляется определение, так что при вычислении символа загружается файл .mx (а затем специальное определение очищается).