一般来说,我需要的是类型转换指令,以便能够例如乘以 true like 5 * true
和 get5
的 sayx * false
和 get 0
。
怎么做这样的事情?
一般来说,我需要的是类型转换指令,以便能够例如乘以 true like 5 * true
和 get5
的 sayx * false
和 get 0
。
怎么做这样的事情?
你可以这样做:
subs([false=0, true=1], expr);
有几种方法可以获得这种效果,您选择哪种方法可能取决于您打算用它做什么的更多细节。
最简单的是使用 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
您还可以尝试使用模块来导出(并因此在交互使用的“顶级”重新定义)增强的*
.
注意。下面这个导出过程的一个更仔细的版本*
只会在作为整个被乘数出现时替换“真”和“假”,而不是在整个表达式中进行替换。(标量表达式中可以有未计算的函数调用,例如,可选参数中出现“真”和“假”。理想情况下,应该不理会这些。)
> 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 被替换时,不会调用 new *
。也有可能解决这个问题,尽管结果显示不是那么好(并且解决方法可能会“破坏”你可能想要的其他东西),
> 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) 的对象实际上是根据对 new 的未评估函数调用*
。因此,当 b=false 被替换时,就会调用 new*
并且可以获得所需的结果。(希望在我忽略的情况下这不会导致无限递归。)