control structure surprise

APL-related discussions - a stream of APL consciousness.
Not sure where to start a discussion ? Here's the place to be
Forum rules
This forum is for discussing APL-related issues. If you think that the subject is off-topic, then the Chat forum is probably a better place for your thoughts !
Post Reply
uwejanza
Posts: 19
Joined: Tue Mar 09, 2010 2:01 pm
Location: Nürnberg, Germany

control structure surprise

Post by uwejanza »

I just came across a surprising piece of code that had been accepted by the interpreter.
Here is a simple example. Verification of numeric data type omitted for the sake of simplicity.


      ∇Test a
:If a<4
⎕←'a is less than 4'
:AndIf a=3
⎕←'a equals 3'
:Else
⎕←'none of the above'
:EndIf


Please, let's not discuss what might be the reaction expected.
Let's just try this out.

Code: Select all

      Test 4
none of the above

Ok.

Code: Select all

      Test 3
a is less than 4
a equals 3

Wow! Both conditions are met and both reactions happen. Is this magic?


Code: Select all

      Test 2
a is less than 4
none of the above

What??? Of course, 2 is less than 4. Nothing else.

Please, don't ask me what kind of result anybody might expect from operational code between an :if condition and an :andif condition. I'd rather see this kind of code faulted by a syntax check at fix time.
I tried in 12.0 Unicode and in 13.0 Unicode, and they both accept that code.


Regards

Uwe
User avatar
Phil Last
Posts: 628
Joined: Thu Jun 18, 2009 6:29 pm
Location: Wessex

Re: control structure surprise

Post by Phil Last »

If you replaced 'none of the above' with 'a is not equal to 3' which actually describes the situation it wouldn't be wrong.

Nevertheless I agree the allowing anything at all between the :If condition and the :AndIf condition is a peculiarity that is almost bound to cause confusion.

All I can say is that it gets even hairier with :OrIf

You'd have a syntax error with the former. I'd abolish the latter from the language.
DanB|Dyalog

Re: control structure surprise

Post by DanB|Dyalog »

I am not sure I understand what the problem is but the way the :if & :andif control structures is defined is fine.
Whatever you put between them is merely a convenient way to prepare for the next :andif (or :orif) statement.
You have to understand how it works in order to use it properly.

If nothing were allowed you'd have to do something like

:if condition1
:andif fndefiningCondition2

where <fndefiningCondition2> would be a function or an expression with all the lines you now put in between right now.

For example:

:if c1
a<-3+X
b<-5+Y
:andif a<b
...

would have to be replaced by
:if c1
:andif (a<-3+X)<b<-5+Y

The former is more readable and therefore more convenient.
But it can be abused and as Phil points out :orif can be more confusing.

But maybe you are confusing :andif and :elseif.
In your example I would simply rephrase the code to be
:if a=3
'a = 3 AND therefore <4'
:elseif a<4
'a is <4 (but not 3)'
:else
'a is >=4'
:endif

If I misunderstood something please explain what you think is wrong.
uwejanza
Posts: 19
Joined: Tue Mar 09, 2010 2:01 pm
Location: Nürnberg, Germany

Re: control structure surprise

Post by uwejanza »

DanB|Dyalog wrote:If I misunderstood something please explain what you think is wrong.


Thanks, Dan. There is nothing wrong.

From other programming languages I know compiler options that enable shortcut evaluation of compound condition expressions connected with AND and OR, so that in a (pseudo-)statement like
      IF (cond1) AND (cond2) AND (cond3)

if (cond1) should fail (cond2) and (cond3) will not be evaluated. When long time ago Dyalog introduced control structures I understood the ANDIF and ORIF control statements as a very nice way of codeing this kind of behaviour explicitly, but not more. So in my codeing practice there are IF statements followed directly by ANDIF or ORIF statements. No intermittent blocks of code. Not even thought about that. Never.

When lately I revisited a function written one year ago I found a block of several lines of code inserted between an IF and an ANDIF statement line that originally had been adjacent lines.

The very possibility of placeing (an unlimited number of) arbitrary lines of active code between IF and ANDIF statement lines took me by surprise, completely. So did the fact that within one IF-ENDIF set of control structure statements more than one of the code blocks between control structure statement lines can come to execution. The latter is a consequence of the former and the behaviour is conforming perfectly with the definition given in the documentation.

DanB|Dyalog wrote:You have to understand how it works in order to use it properly

Yes, you really have to.

Learning never stops.
DanB|Dyalog

Re: control structure surprise

Post by DanB|Dyalog »

From other programming languages I know compiler options that enable shortcut evaluation of compound condition expressions connected with AND and OR, so that in a (pseudo-)statement like
IF (cond1) AND (cond2) AND (cond3) FINAL


The same applies here.
If you trace through APL code with :If and :andif statements you will see that APL skips the block as soon as one of the conditions (:[AND]IF) is false.
To execute the FINAL statement ALL the :andif statements (and the code preceding them) must be evaluated.

The reverse is true for :orif statements: APL will execute the FINAL statement(s) as soon as one is TRUE. All others after will be skipped.
In other works it executes all the statements until an :[OR]IF is TRUE.

What is unusual is that APL allows us to visually (and conveniently) insert code between :XXif .

If cond2 above was a boolean returning fn instead of a simple expression (e.g. IF (x>y) AND (FN2(y)) ...) and you were allowed to trace thru them you would experience the exact same behaviour as in APL. The only difference is that some languages allow you to mix AND and OR and that this behaviour is not always obvious (and may vary from one language to another) whereas APL forbids the mix of the 2 (thanks God).

One thing that confuses people sometimes is the flow of execution when :ORIF statements are involved.
Consider the following:
[1] :IF cond1
[2] :orif cond2
[3] doThis
[4] :endif

If cond1 is true line [2] is skipped and line [3] is executed right away.
If it false line [2] is also executed and depending on the outcome line [3] MAY be executed.
That is fairly well understood by most.

But if cond2 is a very complex statement it may be broken down into more readable, simpler statements like this:
[1] :IF cond1
[2] cond2<-...
[3] :orif cond2
[4] doThis
[5] :endif

If cond1 is true, line [4] is executed right away. If it false cond2 MUST be evaluated and in order to do that line [2] must be executed first.
If you are tracing thru, it may surprise you to see the code on line [2] being executed when cond1 is FALSE.
We naturally assume that the code should be skipped because the condition was FALSE and indeed, if it spans several lines, it looks confusing.

Again if we were to trace thru the lines of code of another language with fns instead of a simple expression we would see the exact same behaviour as in APL.
Post Reply