Вот альтернативное решение, которое я использовал, когда хотел иметь RuleDelayed
приложений с побочными эффектами. Вы используете другую голову, чтобы заменить Set
, пока ваше выражение не окажется справа от формы RuleDelayed
(где оно будет удерживаться атрибутом RuleDelayed
HoldRest
), а затем заменится Set
обратно. Когда я делаю это, мне нравится использовать Module
, чтобы создать для меня уникальный символ. Таким образом, вам не нужно использовать Defer
, который является еще более неприятно скользкой конструкцией, чем Unevaluated
.
Вот пример:
Module[{set},
Attributes[set] = Attributes[Set];
With[{rhs = MapThread[set, Unevaluated[{{x, y, z}, {1, 2, 3}}]]},
"name1" :> rhs /. {set -> Set, List -> CompoundExpression}]]
Причина, по которой символу set
присвоены те же атрибуты, что и Set
, и причина, по которой Unevaluated
присутствует, заключается в том, чтобы убедиться, что это работает, даже если кто-то уже присвоил значение x
, y
или z
.
Другая возможность состоит в том, чтобы обернуть все ваши Set
выражения как замыкания, а затем использовать Scan
для их вызова при оценке RuleDelayed
, например:
With[{thunks = MapThread[Function[{a, b}, (a = b) &, HoldAll],
Unevaluated[{{x, y, z}, {1, 2, 3}}]]},
"name1" :> Scan[#[] &, thunks]]