Клен 13: как превратить истину в 1 и ложь в 0? - PullRequest
3 голосов
/ 02 ноября 2010

В общем, мне нужны инструкции преобразования типов, чтобы можно было, например, умножить на true, например, 5 * true, получить 5, скажем, x * false и получить 0.

. Как это сделатьвещь?

Ответы [ 2 ]

2 голосов
/ 03 ноября 2010

Есть несколько способов получить такой эффект, и выбор, который вы выберете, может зависеть от более подробной информации о том, что вы собираетесь с ним делать.

Самое простое - использовать 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, происходит вызов нового *, и желаемый результат может быть получен.(Надеюсь, это не приведет к бесконечной рекурсии в случае, который я упустил.)

2 голосов
/ 02 ноября 2010

Вы можете сделать это с:

subs([false=0, true=1], expr);
...