For 20 years I've used:
FIND sometable NO-LOCK NO-ERROR. IF NOT available(someForm) OR (Available(someForm) AND (somefield1 EQ NO) AND somefield2 = 3 AND some...) THEN MESSAGE "Case of something". ELSE MESSAGE "Another case".
now few days back I saw a post somewhere around here that used the syntax on the title of post..
I know that the order of operators and logic of complex expresion are to be taken on account.
But wonder, what's the logic of the compiler or runtime AVL (whichever one involved).
In: "IF NOT AVAILABLE(tableX) OR tableX.FieldY = "somevalue" THEN..."
the OR part should be evaluated even in the case that AVAILABLE() is false, but at this point the FIND was unsuccesful, so:
why on earth won't be a NOT AVAILABLE BUFFER error for the tableX.FieldY = "somevalue" evaluation????
Just realized the very few knowledge of 4gl I got.
If the record is not available the first part of the OR expression is true, hence the entire OR expression is true hence no need to evaluate the second expression. This is called short circuiting and it has been a part of the language since V5. In V4 this would have generated an error.
I've done several experiments, and the syntax i've bee using it's what should be used. So the snipet I saw here somewhere it's wrong in this aspect, as the folowing snipet would show a Record not available as expected.
FIND FIRST Table1 WHERE Field1 = 12312312123 NO-ERROR. // it wouldn't find anything IF FALSE OR ( Table1.Field2 = "C") THEN DO: MESSAGE "No" VIEW-AS ALERT-BOX. END.
So, rest my case,
your comparison is slightly off. in the first example "NOT AVAILABLE <table" is TRUE, so it evaulates close to
IF TRUE OR ( Viaje.statusviaje = "C")
In the second example you are always going to evaluate the expression after the OR since FALSE is never able to be TRUE.
The syntax, or better saying, the logic you've been using is redundant. Therefore, there's no need to use it.
The snippet you saw is completely RIGHT. Your example, on the other hand, is logically wrong as the left side of the OR clause will always be false, thus, ABL will evaluate the right side and since the record is not available, ABL will throw an error.
Now, why this snippet is right?
1º ABL evaluate OR from left to right
2º "AVAILABLE" is an ABL function the returns TRUE if the record is available and FALSE if not
Therefore considering the TableX is not available:
/* record not available */ FIND FIRST tableX NO-ERROR. /* Output false */ DISP AVAILABLE TableX. /* Output true because of NOT */ DISP NOT AVAILABLE TableX.
You're misunderstanding things because you didn't understand the usage of NOT.
Let's observe that the AVM evaluates expression clauses from LEFT to RIGHT, not the other way around.
The original snippet was NOT AVAILABLE(tableX) OR tableX.FieldY = "somevalue" I would have written this as AVAILABLE(tableX) AND tableX.FieldY = "somevalue", but the original syntax is fine for the coders purpose.
Note that AVAILABLE(tableX) is a precondition of tableX.FieldY = "somevalue". Hence my preference for the latter syntax.
Indeed Greg,
It was my bad, I swapped all rights for lefts in my whole answer. But in my mind I meant the opposite. LOL
I've edited the post. Thanks.
And I agree with you, using AND is better.
Hi...
I saw the aswers yesterday while on the run, and prepared to came with my sword unsheathed today. But I see that someone commented on the left to right issue.
My point is the following. In the next sentence, if for some reason the first condition fails then AVM will check the SECOND part of the OR clause. and being that the record could be available (OR not) i'll test some condition on it, so I have to make sure that it is available.
IF (NOT AVAILABLE(X1)) OR (AVAILABLE(X1) AND X1.Field1 = "1")
this is simple. I have to do something in case the record wont' exis, or if it exists, do something only if it is some special kind of record (as stated by the Field! being "1"). I use that for a case where customer won't exists, or it exists, but for conditions like addres or so, don't have to be taken on account.
I ended doing this way instead of:
IF NOT AVAILABLE X1 THEN DO:
RUN proc1.
END.
ELSE IF AVAILABLE(1) AND X1.Field1 = "1" THEN
run proc1.
Octavio,
what is the point in checking if record is available, you're already on the else branch where you can trust the record is available :)
if not available(x1) or x1.field1 = '1' then run proc1.
Hi Marian... Yes you nailed a little (big) error.
It came from trying to de-compose (factoring) the MPP (modus ponendo pones) clause that originally took me to the first sintax.
Any way...
What i try to expose, was the fact that a clause like
IF NOT AVAILABLE(x1) THEN DO: ...
END.
ELSE
IF X1.Field1 = "something" THEN DO something else for a case where the record falls outside some use case....
could be expressed like
IF (NOT AVAILABLE(X1)) OR (AVAILABLE(x1) AND X1.Field1 = "something") THEN .....
as the AVM will discard the first condition but to be a able to test for Field1 = "something" ther should be a record on buffer, otherwise it will cast a Record not available....
I'm very sorry for not being able to "think in english", and create this missunderstanding... sorry...
Hi Brian....
You put me to think...
more often than not, I use DO: END. just to help the syntax formatter to format correctly the {&OPEN-QUERY-...} code here and there.
If I left them free, the formatter scrambles the tabbing of following lines...
I'll give it a second tought from now on...
Thanks!
Greetings
> IF (NOT AVAILABLE(X1)) OR (AVAILABLE(x1) AND X1.Field1 = "something") THEN .....
> as the AVM will discard the first condition but to be a able to test for Field1 = "something" ther should be a
> record on buffer, otherwise it will cast a Record not available....
You don't need the second AVAILABLE(x1) after OR, because if the record is not available, the left side of OR will already be TRUE and the right side of OR will not be tried at all! And since it will not be tried, you will not get "Record not available". (Like GregHiggins told you already.) Try it out and see for yourself...
In short: TRUE OR whatever_expression_here = TRUE /* And the right side doesn't get evaluated */
Same for: FALSE AND whatever_here = FALSE