I think this is a macro trick that will be of general interest to the community, and I didn't want to clog up the announcements thread any more (where people might not see it anyway).
With build 1.3.b38, we were given the ability to use an "if" command. If you are familiar with other programming languages, you should recognize "if" as a ternary operator: if(condition,then,else). This is VERY different from
if ( condition)
{ do stuff}
else
{do other stuff},
Before we get to some examples, we should remind ourselves of the basic boolean things. There's a HUGE difference in MapTool between "=" and "==". "=" is the assignment operator, you're familiar with that for putting numbers into variable names. "x=2" stores 2 into x. "==" on the other hand, asks a question, "does this equal that?" That is, "x==2" asks "is x equal to 2?"
Similarly, "x>2" asks "is x greater than 2?"
You cannot put assignments (=) in the "then" or "else" portions of "if(condition,then,else)" So you have to do the assignment before the word if.
So if wanted to emulate the code:
Code: Select all
if (x>y)
x = x*x
else
x = x-1
Code: Select all
{if(x>y, x=x*x, x=x-1)}
You would write instead:
Code: Select all
{x = if( x > y, x*x, x-1)}
Notice that the condition is x > y, and if that is true (we want to use the "then" portion) x = x*x, but if x <= y, we should use the else portion, so x = x-1. So if x is 2, and y is 1, we will find that after this line is run, x = 4, y = 1. However, if x = 1, y = 2, after this code is run, x = 0, y = 2.
Sometimes, you want your code to "do nothing" in the case of the else:
So if you wanted to emulate this code:
Code: Select all
if(x>y)
x = x*x
Code: Select all
{x= if(x > y, x*x, x)}
Let's now graduate to a slightly more sophisticated code:
Suppose we want to emulate a code like this, where we change x in the "if" but change y in the "else":
Code: Select all
if (x > y)
x = x*x
else
y = y*y
Code: Select all
{Control = if(x > y, 1 , 0)}
{x = if(Control==1, x*x, x)}
{y = if(Control==0, y*y, y)}
Any lines having if(Control==1,...) can be thought of as "inside" the if block.
Any lines having if(Control==0,...) can be thought of as "inside" the else block.
This approach allows us to cleanly approach "block if" codes.
Suppose we now want to do:
Code: Select all
if (x > y)
x = x-1
y = x*x
else
y = y+2
x = y
Code: Select all
{Control = if(x>y,1,0)}
{x = if(Control==1,x-1,x)}
{y = if(Control==1,x*x,y)}
{y = if(Control==0,y+2,y)}
{x = if(Control==0,y,x)}
Now we can move up one more level of sophistication, we can do nested-ifs by using two different "control variables".
Suppose we want to emulate this code:
Code: Select all
if (x>y)
x = x-1
if (x>y)
y = x*x
else
y = y+1
else
y = y*2
Code: Select all
{Control1=if(x>y,1,0)}
{x = if(Control1==1,x+1,x)}
{Control2=if((Control1==1)&&(x>y),1,0)}
{y = if((Control1==1)&&(Control2==1), x*x,y)}
{y = if((Control1==1)&&(Control2==0), y+1,y)}
{y = if(Control1==0,y*2,y)}
One very very very important thing to be careful about:
It is tempting to collapse these two lines
Code: Select all
{y = if((Control1==1)&&(Control2==1), x*x,y)}
{y = if((Control1==1)&&(Control2==0), y+1,y)}
Code: Select all
{y= if((Control1==1)&&(Control2==1),x*x,y+1)}
So now let's tackle the problem of "else-if." While it's possible to think of "else-if" as an if statement nested in an else statement, that can get messy. As always, I think an example is the easiest way to illuminate my proposed technique:
Suppose we want to emulate a "switch" styled else-if:
Code: Select all
if (x==3)
x = x*2
else if (x==5)
x = x*x
else if (x==7)
x = x-2
else
x = -1
Code: Select all
{Control=if(x==3,1,0)}
{Control=if((Control==0)&&(x==5),2,0)}
{Control=if((Control==0)&&(x==7),3,0)}
Code: Select all
{x=if(Control==1,x*2,x)}
{x=if(Control==2,x*x,x)}
{x=if(Control==3,x-2,x)}
{x=if(Control==0,-1,x)}
Code: Select all
if (x>y)
x = x*x
else
y = y*2
Code: Select all
{x = if(x>y, x*x,x)}
{y = if(x<=y,y*2,y)}
The first line asks, "is .5 > .3?" it is, so the new value of x is x = .5*.5 = .25 . Ahh, but now, we come to the second line, which "has no knowledge" that the first line ran (and so according to the code we are trying to emulate, this line "shouldn't be run"). Even though the condition for the second line is the logical opposite of the first one, since x has been updated by our code, they are no longer "exclusive." That is, now .25 < .3 is certainly true, so we change y, even though we weren't supposed to. This is why you see this "Control" variable all over my code. It may also be that I'm a control freak?
Anyway, the correct way to implement that code, again, would be:
Code: Select all
{Control=if(x>y,1,0)}
{x=if(Control==1,x*x,x)}
{y=if(Control==0,y*2,y)}
I have one more trick to share. Recently it was discovered (by BigO, I think...correct me if I'm wrong), that a cute way of hiding output is to enclose things in <!-- {code here} --> . We'll be using this trick to show how one might produce output inside of if-blocks, without displaying every line of possible output . Due to an oddity in the parser, you'll be seeing this sort of nonsense a lot "'"+variable+"'". Do not be alarmed. That's a quotation mark, apostrophe, quotation mark. It lets us tell Maptool to store variable as a string (or if you wrote "Stuff", it treats that as a string). Please note that:
OutputString = "'"+OutputString+"'" is the string equivalent of "x=x"
So let's say we want to emulate this code:
Code: Select all
if (x>y)
Hello Cruel World!
else if (x==y)
Hello well balanced World!
else
Goodbye Cruel World!
Code: Select all
<!-- {Control = if(x>y,1,0)}
{Control = if((Control==0)&&(x==y),2,0)}
{OutputString=' '}
{OutputString=if(Control==1,"'"+"Hello Cruel World"+"'", "'"+OutputString+"'")}
{OutputString=if(Control==2,"'"+"Hello well balanced World" +"'","'"+OutputString+"'")}
{OutputString=if(Control==0,"'"+"Goodbye Cruel World"+"'", "'"+OutputString+"'")}
-->{OutputString}
Your questions and comments are encouraged!