Alternative conditions – nested AND and OR

How to do this?
if (condition1 and condition2) or (condition4 and condition3):
perform_action_a()

Macro:
Trigger: (e.g., Hotkey)
Actions:
- If Then Else
- If Any of the following are true:
- All of the following are true:
- Condition 1
- Condition 2
- All of the following are true:
- Condition 4
- Condition 3
- Then:
- Perform Action A

That depends upon what your conditions are. Are they all numeric variables? If so, do this:

image

If they are not numeric variables, there are other ways to solve this. I posted a solution to this problem a few months ago for when they are not numeric variables. I can't find the page right now, but I can rewrite the solution. If you tell me what your conditions are, I can use them in my solution.

I just noticed that two of your conditions are the same. Therefore, you can do this: (I'm using sample conditions. Notice the use of "any" in the second action.)

image

2 Likes

Thank you.
The conditions are probably like this

Actions (v11.0.1)

Keyboard Maestro Actions.kmactions (5.5 KB)

Here's a general structure that might do what you want. I built it with the assumption that "Action A" could be some long mega-step thing, so you'd only want to have it there once.

And-Or-And conditional.kmmacros (8.9 KB)

It uses a set of wrapped If-Thens, where the second is the "Else" condition of the first. So if 1 and 2 don't, then the 1 and 3 "If" runs. In both, a flag is set if the conditions are met. Then the flag value is checked, and if set, the desired action is run.

There are numerous ways to do this, but my brain understands this method :).

-rob.

1 Like

Here's another way of doing this. There are two IF statements inside a Try action, and if either of those IF conditions are true, (and you aren't limited to calculation conditions) then a "Throw 1" action is executed, which results in the "Tink" being displayed. If neither of the conditions are true, the Try action exits without performing the Tink action. Just be sure you turn off the notification flag in the Throw actions, so you don't get a pop-up notification. I consider this easy to understand, but some people may disagree. It works for me, and I use it.

image

1 Like

This can also be rewritten as

if condition 1 AND (condition 2 OR condition 3)

So:

image

2 Likes

Thank you
if (condition1 and condition2) or (condition3 and condition4):
perform_action_a()
If it is condition 3 and condition 4, is there a better way?

My method, below, doesn't require any variables to evaluate the conditions. So I like it.

image

But it seems to execute all the if conditions, and the two if statements don't seem to be an 'or' relationship.

But it seems to execute all the if conditions, and the two if statements don't seem to be an 'or' relationship.

If either of my two IF actions are true, it branches to the the "Tink" block of code. If neither are true, it exits the Try action. That is indeed an "OR" relationship. If you try it out, I'm sure you will be delighted with the result, because it's simple and doesn't require any variables. But if it's too hard to understand, you can use a different solution.

This can be rewritten as

if (condition1 and condition2)
   execute
      perform_action_a()
   otherwise
      if (condition3 and condition4)
         execute
            perform_action_a()
         otherwise
            -- do nothing
      end if
end if

image

Whether you go with this "explicit" route, @Airy's "throw" method, or do an intermediate evaluation of your conditions to get true or false for each then use those in a calculation as in post 2 above will very much depend on how you think about things (and, to an extent, the conditions you want to use).

1 Like

I just tested it, it will show test1 and test2, and I only want to show one of them, only test2 will show when test1 doesn't show
Try/Catch Action (v11.0.1)

Try-Catch.kmactions (3.8 KB)

Thank you, it works. I'm wondering if there's a simpler method, because if there are too many conditions, this embedding looks quite complex.

You haven't set it up as @Airy did. His method is neat, but can be a tad confusing at first glance.

The method boils down to

try
   if (condition1 and condition2)
      throw an error
   end if
   if (condition3 and condition4)
      throw an error
   end if
catch -- only executes on error
   perform_action_a()
end try

So the first test is true an error is thrown and you jump straight to the catch and perform your action. If it isn't you go to the second test -- if that's true, an error is thrown and you jump to the catch. If neither are true no error is thrown and the catch block never executes.

Complex conditions require complexity to resolve them! You can move that complexity around -- for example, by evaluating your conditions individually to true|false first and then using a single test to evaluate the whole -- but you can't get away from it entirely.

But it really does depend on what your conditions are, and "condition1" etc doesn't give us much of a clue. Each case is different, which is why it's good to have a bunch of tools in your toolbox.

I'm not upset if he finds my solution too confusing. But my solution is nearly perfect because it doesn't require any variables, or any replication of conditions, or any replications of the code that you want to execute.

I still don’t understand. Can you help me modify this macro?
Try/Catch Action (v11.0.1)

Try-Catch.kmactions (3.8 KB)

Move one of your "Display"s into the bottom-most "otherwise execute" section. Then add "Throw" actions to each of the "If"s "execute" sections. You want it to look like @Airy's screenshot in Post 2.

Yes, I'm being evil and not posting a fix because this is one that you need to work through yourself so you can understand why it works :wink:

I was also being evil when I wrote my solution, for the same reason.

OK, I am a foreigner and English is not my native language, so it is difficult to understand.