Есть несколько способов получить такой эффект, и выбор, который вы выберете, может зависеть от более подробной информации о том, что вы собираетесь с ним делать.
Самое простое - использовать 2-аргумент eval
(илиsubs
, так как оценка должна происходить из-за автоматического упрощения для продукта с точным 1 или 0).
> eval( 5*true, [true=1,false=0]);
5
> eval( x*false, [true=1,false=0]);
0
И, конечно, вы можете создать процедуру для обработки этой оценки,
> T := expr -> eval(expr,[true=1,false=0]):
> T( 5*true );
5
> T( x*false );
0
Вы также можете попробовать использовать модуль для экспорта (и, следовательно, переопределения на «верхнем уровне» интерактивного использования) расширенного *
.
nb.Более осторожная версия этой экспортированной процедуры *
, приведенная ниже, будет заменять только «истину» и «ложь», если они встречаются как целые мультипликаторы, и не будет выполнять замену во всем выражении.(Скалярное выражение может содержать в себе неопределенные вызовы функций, при этом «истина» и «ложь» появляются, скажем, в необязательных аргументах. В идеале их следует оставить в покое.)
> M:=module() option package; export `*`;
> `*`:=proc(ee::seq(anything))
> :-`*`(op(eval([ee],[true=1,false=0])));
> end proc;
> end module:
> with(M):
> 5*true;
5
> x*false;
0
> a*b*c;
a b c
> eval( %, b=false ); # this doesn't play along
a false c
Обратите внимание, как происходит подстановка'false' в последнем результате не дало 0. Это потому, что результат a * b * c (для неизвестных a, b и c) находится в глобальном выражении: - *
, а не новый*
.Таким образом, когда подставляется b = false, вызов нового *
отсутствует.Возможно, можно обойти это тоже, хотя получающийся дисплей не так хорош (и обходной путь, скорее всего, «ломает» что-то еще, что вы могли бы ожидать для всего этого),
> M:=module() option package; export `*`;
> `*`:=proc(ee::seq(anything))
> local res;
> res:=:-`*`(op(eval([ee],[true=1,false=0])));
> if type(res,:-`*`) then
> 'procname'(op(res));
> else
> res;
> end if;
> end proc;
> end module:
> with(M):
> 5*true;
5
> x*false;
0
> a*b*c;
`*`(`*`(a, b), c)
> eval( %, b=false );
0
В этом последнемВ приведенном выше примере объект, который выглядит как *
(*
(a, b), c), фактически находится в терминах неоцененных вызовов функций для нового *
.Следовательно, когда подставляется b = false, происходит вызов нового *
, и желаемый результат может быть получен.(Надеюсь, это не приведет к бесконечной рекурсии в случае, который я упустил.)