Maple 13: how to turn true into 1 and false into 0? - boolean

generaly what I need is type transformation instructions to be capable of for example multipliiing on true like 5 * true and get5 of say x * false and get 0.
How to do such thing?

You can do it with:
subs([false=0, true=1], expr);

There are several ways to get such an effect,and which you choose may depend on more particulars of what you intend on doing with it.
The simplest is to use 2-argument eval (or subs, since evaluation should occur due to automatic simplification for a product involving exact 1 or 0).
> eval( 5*true, [true=1,false=0]);
5
> eval( x*false, [true=1,false=0]);
0
And of course you can create a procedure to handle that evaluation,
> T := expr -> eval(expr,[true=1,false=0]):
> T( 5*true );
5
> T( x*false );
0
You could also try using a module to export (and thus redefine at the "top-level" of interactive use) an enhanced *.
nb. A more careful version of this exported procedure * below would only replace 'true' and 'false' if occurring as entire multiplicands, and not do replacement throughout all of the expression. (A scalar expression can have unevaluated function calls in it, with 'true' and 'false' appearing in, say, optional arguments. Ideally, these should be left alone.)
> 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
Notice how the substitution of 'false' in that last result didn't produce 0. It's because the result of the a*b*c (for unknown a,b, and c) is in terms of the global :-* and not the new *. So when b=false is substituted there's no call to the new *. It may be possible to work around that too, although the resulting display is not so nice (and the work-around likely "breaks" something else you might intend for all this),
> 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
In that last example above, the object that looks like *(*(a, b), c) is actually in terms of the unevaluated function calls to the new *. Hence when b=false is substituted there is a call to the new * and the desired result can obtain. (Hopefully this doesn't lead to an infinite recursion in a case I've overlooked.)

Related

Julia macro for generating boolean functions

I have a program that often has the boolean algorithm pattern of: (f(a) && g(b)) || (f(b) && g(a)).
For example,
if ((isA(event[1]) && isTens(event[3])) || (isA(event[3]) && isTens(event[1])))
cnt += 1
end
How can I use a macro, #pmacro, to do the same, so to be called as such:
if (#pmacro(isA(), isTens(), event[1], event[3]))
cnt += 1
end
So far, I tried something like this
function isCombination(f, g, e1, e2)
if (f(e1) && g(e2)) || (f(e2) && g(e1))
true
else
false
end
end
And,
julia> isCombination(BJcore.isA, BJcore.isTens, event[1], event[3])
Works but, should I use meta-programming here?
You don't need a macro for that. Since Julia supports higher order programming, you can define a function - I'll call it predicate here - that accepts the functions f and g as arguments and performs the required check.
julia> predicate(f, g, a, b) = (f(a) && g(b) || f(b) && g(a))
predicate (generic function with 1 method)
julia> predicate(iseven, isodd, 4, 3)
true
julia> predicate(iseven, isodd, 3, 3)
false
julia> predicate(iseven, isodd, 3, 4)
true
Edit: The edit to the question happened while I was writing the answer, but you've hit upon the solution. isCombination and predicate are pretty much the same function.
As for metaprogramming: when there's a non-metaprogramming solution to a problem, the answer to "should I use metaprogramming" is almost always no. Metaprogramming is a powerful tool, but can make your code harder to read and maintain unless applied judiciously and with care.

Why does this if statement give an output despite the && conditions not being satisfied?

I have been trying to execute a piece of code with some if conditions. This is a simple version of it.
X=100;Y=100;
if ((((X+1) && (Y+1))<=99) && (((X+1) && (Y+1))<=102))
disp(X);
end
Despite both X and Y not satisfying the first condition, I still get the output as 100. I have tried all combinations of & and && to make the and operations in the work. I checked the difference between the two and I found that & is a logical bit-wise operator while && is a short-circuit operator, which probably doesn't change much in this context. What's the error with this syntax?
Of course the code works when I do this:
X=100;Y=100;
if (X+1)<=99 && (Y+1)<=99 && (((X+1) && (Y+1))<=102)
disp(X);
end
But this is so inefficient when there are lot of conditions and each sub-condition must include the constraints. I'm sure this must be answered somewhere and this question might be a duplicate, so please point me to the answer.
So it looks like you understand what (X+1)<=99 && (Y+1)<=99 does. Let's look at ((X+1) && (Y+1))<=99:
&& requires a logical value on each side. a && b will turn a and b into logicals, effectively becoming a~=0 && b~=0. Thus:
((X+1) && (Y+1) ) <= 99
((X+1)~=0 && (Y+1)~=0) <= 99
( true && true ) <= 99
1 <= 99
true
Of course the truth value of (X+1)~=0 and (Y+1)~=0 could be different, but here you see this. In MATLAB, true is equal to 1 in a non-logical context, as when compared to 99.
If you want to simplify this expression, use max instead of &&:
X=100;Y=100;
if max(X+1,Y+1)<=99 && max(X+1,Y+1)<=102
disp(X);
end
If the max of a and b is smaller than 99, then both a and b are smaller than 99.
(Obviously, the statement can be further simplified to if max(X+1,Y+1)<=102, since if the second inequality holds than so must the first.)

Does IEC-61131 Structured Text allow comparison of boolean operands?

I'm building a parser and type checker for Structured Text. ST is a derivative of Pascal.
It is clear that ST allows equality comparison of two declared real variables X and Y as
X = Y
It is also clear you can write
X <> Y
and
X > Y
If I have two declared boolean variables A and B, is
A = B
legal? Pascal would certainly say so. The reference documents I have for ST (including an Australian version of the 2004 standard, and several vendors implementations) are unclear.
Can I write:
A > B
and what does it mean?
[In the abstract, I'm interested in the same questions for comparing strings. Brownie points for addressing that issue too].
[No, I can't just try it on a real controller; I don't actually have one and the nearest one is effectively two days away from me.]
What's the answer, and what's the reference document you consulted that shows the answer?
The answer to this question really depends on IDE. Although there is a standard for ST, every vendor implement it little bit differently.
In general this is valid statement.
VAR
a, b: BOOL;
END_VAR
IF a = b THEN
// Do something
END_IF
Here is what is in IEC 61131-3 draft. Unfortunately it is not open document and costs money that is why I cannot post it here or provide a link.
https://webstore.iec.ch/publication/4552
GT > Decreasing sequence: OUT := (IN1>IN2) & (IN2>IN3) & ... & (INn-1 > INn)
GE >= Monotonic sequence: OUT := (IN1>=IN2)&(IN2>=IN3)& ... & (INn-1 >= INn)
EQ = Equality: OUT := (IN1=IN2) & (IN2=IN3) & ... & (INn-1 = INn)
LE <= Monotonic sequence: OUT := (IN1<=IN2)&(IN2<=IN3)& ... & (INn-1 <= INn)
LT < Increasing sequence: OUT := (IN1<IN2) & (IN2<IN3) & ... & (INn-1 < INn)
NE <> Inequality (non-extensible) OUT := (IN1 <> IN2)
This also means that in some IDEs you can use
IF EQ(a, b) THEN
// Do something
END_IF
And this should be valid as well.
Can I write:
A > B
and what does it mean?
If A greater than B this expression will return TRUE otherwise FALSE.

Why does this Julia macro _not_ require `esc`?

I found an example of an unless macro in Julia here written as follows:
macro unless(test, branch)
quote
if !$test
$branch
end
end
end
However, when I try to use it, it fails (apparently there is a hygiene problem, but I can't figure it out exactly). Here is the test that I used:
x, y = 0, 1
#unless (x == 5) begin # should execute
y = 3
end
#unless (x == 0) begin # should not execute
y = 5
end
#assert y == 3 # FAILS! SAYS y is 0
Now I can make this work by escaping only the branch, not the test:
macro unless(test, branch)
quote
if !$test
$(esc(branch))
end
end
end
My question is: why does it suffice to only escape the branch but not the test? Now I did try macroexpanding. In the first case, without the esc, I get this:
julia> macroexpand(:(#unless (x == 5) begin y = 3 end))
quote # none, line 3:
if !(x == 5) # none, line 4:
begin # none, line 1:
#2#y = 3
end
end
end
Now even though neither macro parameter was escaped, ONLY the y was gensymed! Can anyone explain why this was the case? (I know that the second version works because when I escape the branch, The y doesn't get gensymed and the macro expands to y = 3 as expected. But I'm totally at a loss as to why the x was not gensymed even though there was no use of esc.)
Refer to Julia doc:
Variables within a macro result are classified as either local or
global. A variable is considered local if it is assigned to (and not
declared global), declared local, or used as a function argument name.
Otherwise, it is considered global....
So in this case test part does not assign anything therefore it's variables considered global, but in branch part, y got assigned thus it is considered local and assigning new value to it do not change y in the module scope.

Immediately invoked named functions

A friend of mine posed an interesting question to me today about how to write immediately invoked named functions in CoffeeScript without hoisting the function variable to the outer scope.
In JavaScript:
(function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })(5);
The best I could come up with in CoffeeScript:
do -> do factorial = (n = 5) ->
if n <= 1 then 1 else n * factorial(n-1)
looks a bit awkward. Is there a better way to do this?
You can’t. CoffeeScript doesn’t support this kind of thing at all, except via inline JavaScript:
result = `(function factorial(n) {`
return if n <= 1 then 1 else n * factorial(n-1)
`})(5)`
(No indenting allowed, either.) CoffeeScript will insert some semicolons for you, too, so no using it in expression context.
Then again…
-> if n <= 1 then 1 else n * arguments.callee n-1
(don’t do that)