Используя атрибут HoldAll
, упомянутый ninjagecko, я смог найти решение.
На самом деле произошла другая проблема, которую я не смог сразу увидеть. В частности, моя функция не соответствовала шаблону, как я и думал.
Я думал, что моя первоначальная проблема заключалась в том, что Mathematica автоматически упрощала мои выражения, и мне нужно было лениво оценивать передаваемые параметры для правильного поведения.
На самом деле я забыл, что существует несколько способов представления выражений в Mathematica. В качестве примера игрушки рассмотрим следующую функцию, которая извлекает числитель и знаменатель дроби:
ExtractNumDem[Fraction[a_, b_]] := {a, b}
(* Already incorrect, ExtractNumDem[4 / 100] gives {1, 25} *)
Простое добавление атрибута HoldAll (или HoldFirst even) приводит к другой проблеме:
SetAttributess[ExtractNumDem, HoldAll];
ExtractNumDem[4 / 100] (* Gives ExtractNumDem[4 / 100] *)
Выражение 4 / 100
фактически равно Times[4, Power[100, -1]]
. Чтобы исправить эту вторую проблему, мне пришлось добавить определение для дробей, которые выглядят так:
ExtractNumDem[Times[a_, Power[b_, -1]] := {a, b}
ExtractNumDem[4/100] (* Now gives {4, 100} *)
Мое решение для устранения проблемы в моем первоначальном ответе основывалось на том же самом принципе. Вот некоторый код, чтобы увидеть проблему, с которой я столкнулся:
ClearAll[ExtractNumDem]
ExtractNumDem[Rational[a_, b_]] := {a, b}
ExtractNumDem[4 / 100]
SetAttributes[ExtractNumDem, HoldAll];
ExtractNumDem[4 / 100]
ExtractNumDem[Times[a_, Power[b_, -1]]] := {a, b}
ExtractNumDem[4/100]