Поиск…


замечания

Это должно объяснить порядок оценки как можно более однозначным образом. Это, вероятно, менее идеально подходит как введение в исполнение Mathematica. Он основывается на tutorial/Evaluation странице tutorial/Evaluation Mathematica, объясняя порядок применения различных правил и объясняя, какие функции обрабатываются специально механизмом оценки.

Контексты оценки

В любой момент код выполняется в контексте. Контекст состоит из набора правил замены (его словаря) и приоритета, в котором они должны оцениваться. Мы группируем пять видов контекстов с четким поведением и ограничениями: * Установить контекст * Контекст блока * Контекст соответствия * Контекст ReplaceAll * ReplaceRepeated Context

Установить контексты

Контекст Set - это тот, который определен некоторым набором операций Set [] (функция, обычно называемая = ). Основным примером является первичная среда исполнения. Его словарь изменяется всякий раз, когда Set [] запускается в переменной, которая не имеет других областей. Другие экземпляры Set Contexts возникают из пакетов. Контекст пакета связан с его родительским контекстом тем, что любые шаблоны внутри пакета также становятся шаблонами в родительском контексте с соответствующим префиксом (определение foo[x_]=3*x InnerPackageName\ foo[x_]=3*x становится InnerPackageName\ foo [x _] = 3 * x `).

Set Contexts может содержать только правила, имеющие связанный с ним «тег», строку, связанную с головой, чтобы быстрее определить применимость правила. Приложение Set[yyy_,zzz_] определит тег, проверив, является ли yyy символом. Если это так, то это тег. В противном случае он проверяет yyy[[0]] , затем yyy[[0,0]] и так далее. Если в какой-то момент это определено как символ, то это берется как тег. Если это вместо него несимвольный атом (такой как String, Integer, Real ...), тогда он выдает ошибку и никакое правило не будет создано.

Функции UpSet (записанные ^= ) и TagSet (написанные /: / = ) (и их кузены UpSetDelayed и TagSetDelayed) позволяют связать правило с другим тегом. Существует еще ограничение, что тег должен быть символом. UpSet свяжет его с каждым из аргументов в выражении или головой, если они являются функцией с символом для головы. Например, вызов UpSet на f[a,b,c+d,e[f,g],5,h[i][j][k],p_] будет связывать созданное правило с a , b , e , и h . Аргументы c+d , 5 и p_ будут иметь ничего общего с ними и вызовут сообщение об ошибке. Назначение будет по-прежнему преуспеть в каждом из аргументов и (как будет указано позже в оценочном порядке), оно все равно будет работать практически для всех целей. TagSet похож на UpSet, но вы можете указать ровно один символ для тега. Символ все равно должен быть чем-то, что можно установить с помощью Set или UpSet (символ верхнего уровня в голове или аргументы). Например, TagSet[f, f[a,b[c]], 2] является приемлемым и ассоциирует определение с f ; TagSet[a, f[a,b[c]], 2] и TagSet[b, f[a,b[c]], 2] также приемлемы, но TagSet[c, f[a,b[c]], 2] нет.

Правила внутри контекста требуют приоритета приложения, поскольку для данного выражения может быть множество правил. (Это также верно в ReplaceAll и ReplaceRepeated Contexts, но они обрабатывают его совсем по-другому). Приоритет, как правило, предназначен для соответствия специфичности шаблона. Учитывая выражение a[q][b[c,d],e[f,g]] для оценки, с учетом того, что голова и аргументы оцениваются как полностью, как они будут (см. Ниже TODO), начните с поиска правил, помеченных с b которые применяются; затем правила, помеченные знаком e ; затем правила помечены знаком a . В каждом наборе правил поддерживается порядок для тех, которые связаны с данным символом. Правила без пробелов (например, f[a,b]=3 ) автоматически помещаются вверху и сортируются в каноническом порядке (порядок сортировки). Каждый раз, когда добавляется новое правило, ядро ​​будет проходить через список; если какое-то правило имеет то же самое LHS, то оно заменяется на месте. В противном случае, это делает сравнение специфики. Если определено, что правило X уже в списке «менее специфично», чем новое правило Y, тогда Y помещается непосредственно перед X. В противном случае он продолжается через список. Если правило не менее конкретное, тогда правило помещается в конец списка. Проверка специфичности более сложна и более подробно описана в разделе ниже.

Специфичность правила

* Если два выражения не имеет экземпляра BlankSequence ( __ ), BlankNullSequence ( ___ ), опциональные ( : ), альтернативы ( | ), повторенный ( .. ), RepeatedNull ( ... ) или необязательные аргументы ( _. ), То их можно сравнить структурно. Учитывая два эквивалентных дерева выражений X и Y, где все пробелы в Y также являются пробелами в X, но X имеет пробелы, где Y не имеет значения, то Y является более конкретным. * Если два выражения эквивалентны, за исключением того, что некоторые экземпляры _ были заменены на __ в другом выражении, или __ были заменены на ___ , то первая более конкретна. * Если зачистки еще один Дополнительно ( : ) (или по желанию _. ) Термины дает другое выражение, то последний более специфичен. * Если определенный набор вариантов из альтернатив дает другое выражение, то последнее более конкретное. * Если заменить все экземпляры RepeatedNull[foo] на Repeated[foo] или Repeated[foo] с помощью foo , выдает другое выражение, то последнее более конкретное. * Некоторые комбинации этих правил могут применяться сразу, но в настоящее время это не так знаете, что это за дела. * Комбинации выражения, такие как _List и {___} теоретически, должны относиться к ним одинаково, но сравнение представляется странно зависящим от контекста, иногда ранжируя их так или иначе.

Блочный контекст

Контекст блоков более ограничительный, поскольку LHS правила в блоке может быть только символом. То есть, только определения вида f=2+x , а не f[x_]=2+x . (Обратите внимание, что с практической точки зрения функции все еще могут быть сконструированы с такими определениями, как «Установить [Блок] связан с его родительским контекстом, поскольку любые новые определения во время оценки Блока будут перенаправлены в окруженный контекст как обычно, но это будет «затенять» некоторый набор переменных, предоставляя определения, которые могут скрыть объекты окружающего контекста. Определения из окружающего контекста все еще доступны во время оценки внутреннего выражения. Поскольку может быть только определение, связанное с символом, нет понятия приоритета, как указано выше.

Согласованный контекст

После согласования правила существуют локально связанные определения для переменных. Это происходит лексически . Иными словами, он подпадает под определение границ переменных в выражении, не оценивая ничего другого. Только после того, как все последующие действия произошли, он начинает оценивать выражение в целом снова сверху. Основной способ создания согласованных контекстов - это правило из набора контекста или правила. Например, в

g[a_]:=a+x;
f[x_]:=x+g[1];
f[x^2]
(*Yields 1+x+x^2 *)

После сопоставления правила f[x_] с f[y] символ x привязан к значению x^2 . Он выполняет одну подстановку, но поскольку он не оценивает g , он возвращает x^2+g[1] . Затем он снова оценивается в окружающем Set Context и становится 1+x+x^2 . Существенная разница в оценке в согласованном контексте заключается в том, что замена не является рекурсивной. Когда он составляет x->x^2 , он не повторяется даже по собственным результатам.

Соответствующие контексты также создаются с помощью функции « With , « Module , « Function и « Replace . Многие другие функции создают их внутренне, например, Plot использует этот тип контекста при оценке отображаемого выражения.

ReplaceRepeated Context

ReplaceRepeated Context создается при возникновении любого приложения ReplaceRepeated . Это отличается тем, что оно может иметь любое выражение, как правило, LHS, включая те, у которых нет тега, например _[_] . В этом смысле это самый гибкий контекст. Он также может включать несколько правил, которые могут конфликтовать, поэтому он должен поддерживать приоритет. Контекст ReplaceRepeated Context сначала применит первое правило в списке, где это применимо. Если он не соответствует, он переходит ко второму и так далее. Если в какой-либо момент правильное совпадение, оно возвращается к первому правилу и начинается снова. Если в какой-то момент применяется правило, и никаких изменений не происходит, он выйдет - даже если другие правила в списке будут внесены изменения. Это означает, что любые менее конкретные правила, ранее описанные в списке, не позволят использовать более поздние правила. Кроме того, размещение a_->a в передней части списка правил приведет к немедленному завершению всего ReplaceRepeated .

ReplaceAll Context

Контекст ReplaceAll создается при возникновении любого приложения ReplaceAll . Его функционирование аналогично функционированию ReplaceRepeated в том, что приоритет приоритета его правила идет в порядке в списке, когда два могут применяться на одном уровне выражения. Тем не менее, это похоже на согласованный контекст, поскольку замененное содержимое не оценивается дальше, даже не по более поздним правилам . Например, x/.{x->y,y->z} дает y . Таким образом, неверно просматривать приложение ReplaceAll, применяя каждое правило по очереди. Вместо этого он пересекает дерево, ища подходящие правила. Когда он находит что-то, что соответствует, он выполняет замену, а затем возвращает дерево, не пересекая новое дерево. Также стоит отметить, что он пытается применять правила сверху вниз, возможно, выходя из строя списка в результате. Например,

Cos[1 + 2 Sqrt[Sin[x]]] /. {Cos[_] -> 5, Sin[_] :> (Print[1]; 10)}
Cos[1 + 2 Sqrt[Sin[x]]] /. {Sin[_] :> (Print[1]; 10), Cos[_] -> 5}

оба дают 5 без печати. Поскольку Cos[_] соответствует более высокому уровню дерева, он применяется первым.

Hold и Evaluate и выполнить заказ

Порядок оценки с выражением выражается следующим образом: * Оцените голову как можно полнее * Если у главы есть свойство Hold ( HoldFirst , HoldRest , HoldAll , HoldAllComplete ), то * Проверьте соответствующие аргументы. Если это не HoldAllComplete , проверьте, является ли голова Evaluate . Если это так, то разделите Evaluate и отметьте, что он будет оценен в любом случае. * Проверьте аргументы для экземпляров Unevaluated и Unevaluated их по мере необходимости, если нет свойства HoldAllComplete . * Сгладить аргументы из Sequence s, если не применяется SequenceHold . * Применяйте атрибуты Flat , Listable , Orderless если применимо. * Применить оценку, связанную с значениями аргумента (их теги) * Применить оценку, связанную с головой.

Когда оценка выражения завершена, он отмечен как полностью оцененный. Последующие оценки, которые попадают в это выражение, не будут пытаться его оценить. Если новое правило определено для символа, который происходит внутри, тогда флаг удаляется, и его можно снова оценить. Заметным местом, в котором это «не удается», является Condition ( \; ): условное правило не может применяться к первоначальной оценке. Если несвязанный символ меняет значения, и теперь условие применимо, выражение по-прежнему помечено полностью оцененным и не будет изменено в результате. Функция Update уникальна тем, что она будет оценивать свой аргумент независимо от его уже оцененного состояния или нет, заставляя сортировать «кеш-флеш».

Есть целый ряд других функций , которые часто рассматриваются как исключительные, такие Hold , Defer , ReplacePart , Extract или ReleaseHold . Эти эффекты могут быть достигнуты с помощью атрибутов (таких как HoldAll ) и определения нормальной функции и не должны обрабатываться оценщиком однозначно.

Применение `ReplaceAll` и` ReplaceRepeated`

Пример того, как ReplaceAll применяет правило не чаще одного раза, а ReplaceRepeated будет делать это в цикле, но всегда перезапускает приложение из первого правила.

x + a /. {
  a_ + z :> (Print[0]; DoneA),
   a_ + x :> (Print[1]; y + z), 
   a_ + y :> (Print[2]; DoneB)}

(* Prints "1", yields "y+z" *)

x + a //. {
  a_ + z :> (Print[0]; DoneA),
   a_ + x :> (Print[1]; y + z), 
   a_ + y :> (Print[2]; DoneB)}

(* Prints "1", then prints "0", yields "DoneA" *)

Сортировка пузырьков

Сортировка пузырьков с правилами и заменами:

list = {1, 4, 2, 3, 6, 7, 8, 0, 1, 2, 5, 4}

list //. {fsts___, x_, y_, lsts___} :> {fsts, y, x, lsts} /; y < x

(* 
    Out[1] := {1, 4, 2, 3, 6, 7, 8, 0, 1, 2, 5, 4}
    Out[1] := {0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8}
*)


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow