Control Structures in APL 
Author Message
 Control Structures in APL

I have been following the discussion on control structures for some time, and have
a few comments.  

This discussion has been going on along time.  I have the proceedings of an APL conference
that took place about 20 years ago in which APLGOL was discussed.  In this case, Algol like
control structures were added to APL, and a preprocessor was used to compile the APLGOL code
into APL.  After all of this time, there still is no standard for APL control structures; yet
the language has changed in other significant ways (e.g. nested arrays).  

Quote:
---- (Bernhard Strohmeier) writes:

>The character set:
>Do you really LIKE the J character set? J code looks as if somebody has
>played tennis with the keyboard. J code is a complete MESS.

I agree, J code is even harder to read and understand than APL; however, it is easier to publish
over the internet.

Quote:
>Who cares for control structures? I SWEAR that I will not even take a
>look at APL*PLUSIII+n as long as they keep on including all this windows-
>stuff, do-while loops, and OO-mickey-mouse-features, but neither complex
>arithmetic nor adjustable numerical precision.

I've used the windows-stuff in APL*PLUS III to build a database application.  The interface isn't
quite as polished as Visual Basic, but the application was much easier to write.  It was nice to
be able to manipulate the entire contents of a list box at once.  The Windows environment provides
a very nice programming environment, better than any other APL I've used.

Quote:
---- (William Chang) writes:
>Here are three orthogonal, complementary proposals for adding control
>structures to APL.  Critiques are welcome.

>(1) Controlled statements

><WHILE>  {control} -> {block}
><IF>     (control) -> {if-block} {optional-else-block}
><CASE>   (control) -> (case1) {block1} ... (caseN) {blockN} () {default}

>(2) Controlled expressions

><EXPR>   {expr1} {expr2} ... {exprN} [control]

>(3) Local functions and subroutines

><GOSUB>  (control) -> label(val1;val2;...;valN)
><DEFN>   label (arg1;arg2;...;argN) ;local1;...;localK : {block}
><RETURN> <- optional-result

I prefer the Manugistics control structures over these proposals
for the following reasons:

1) The resulting code is easier to read and understand (my opinion :)
2) Manugistic's control structures are probably easier to implement.
3) They are faster than branches with Manugistics implementation.
4) The colon prefixed key words (especially with color highlighting) make
   the structure of an algorithm apparent at a glance.

For the Manugistic's control structures, I dont like the following:
1) IF statements require at least 3 statements (diamonds can separate the parts)
       :if condition
          statement
       :endif
   For the simple cases, I would prefer to write something like
       :if condition :then statement  (i.e. BASIC's conventions)

2) :GOTO and :RETURN seem useless.  :RETURN is not even as powerful as the
   standard APL technique of branching to 0, since it is unconditional.

3) The control structures can only be used within functions


Quote:

>I think J is showing the way (or was): operators as control
>structures, along with function assignment and  "nonce functions",
>(using { and } as delimiters for APL) and function arrays (gerunds).
>I don't see why we can't put this functionality in APL2. A lot of it
>is already in Dyalog APL.

I agree; I would especially like to see J's ability to compose functions added to APL.

Quote:
>With these in place, the operater-style control structures can allow
>for multiple, parallel, independent "function" execution, based on
>possible *vector* controls. This seems much more "APL-ish" than
>control words.

The resulting could possibly be slower in an "APL-ish" solution.
Consider the problem of evaluating a n element continued fraction f

  f[1] + {divide} f[2] + {divide} f[3] + {divide} ... + {divide} f[n]

In J, because functions can be composed, we can simply write:

   (+%)/f    e.g. (+%)/1 2 2 2 2 2 2 2 2    returns  1.41421

In Manugistics APL, If we define a function plusrecip

   {del} z <- a plusrecip b
   [1] z <- a plusrecip b
   {del}

then we can evaluate the continued fraction by   plusrecip / f
for example:   plusrecip / 1 2 2 2 2 2 2 2 2
returns a close approximation to the square-root of 2.

Because of the function call overhead to plusrecip, this is actually 50% slower in
Manugistics APL III, than a function that uses a for-loop.

   [1] z <- {take} f <- {reverse} f
   [2] :for i :in 1 {drop} f
   [3]   z <- i + {divide} z
   [4] :endfor

Quote:

>I have three problems with this (APL*III)
>1) *english* reserved words (redefinable in J?)

The *english* reserved words are similar to the ones used in conventional languages
(e.g. Ada).  Its likely that most APL programmers could easily understand code that uses
the Manugistics control stuctures; even if they haven't seen them before.  This is
probably not true for the other control structure suggestions.

I still like the idea of adding blocks {...} to APL as first class objects, and having
the execute operator accept blocks as well as strings.  A block would essentially be
equivalent to an anonymous function with no arguments.  Potentially, blocks can be
implemented more efficiently than strings, since they can be stored in a tokenized form.

Kim



Thu, 20 Feb 1997 14:07:16 GMT  
 Control Structures in APL

Quote:

>This discussion has been going on along time.  I have the proceedings of an
>APL conference that took place about 20 years ago in which APLGOL was
>discussed.  In this case, Algol like control structures were added to APL,
>and a preprocessor was used to compile the APLGOL code into APL.  After all
>of this time, there still is no standard for APL control structures; yet the
>language has changed in other significant ways (e.g. nested arrays).

We are at the mercy of the APL vendors--preprocessors are fine for testing
out ideas, but are no good for real use, because of the complexities added
to program development and debugging.

I believe, part of the problem is that previous proposals tried to tackle
several things at once, and ended up either too complex or too big a step.
The discussion on c.l.a. has shown that there are several goals--blocks,
complex expressions, local functions, at least.  While a single paradigm
may deal with all of these, it is not likely to be optimal in every case,
and will be all-or-nothing.  So far we got nothing.

Eke has argued for the "left-tack" (i.e. "where").  Raul made the point that
expressions spanning multiple lines must be evaluated bottom to top.  On the
other hand I believe there's a place for the "diamond" <> and traditional
top to bottom flow.  My point is that the goals and requirements are different
and cannot be satisfied with a single control structure.  I have tried to
clarify this basic distinction, between controlled expression and statement.
While controlled expression may seem more general, it poses greater design
and implementation problems.  It also seems more suited for the "definite" for
loop than the "indefinite" while loop (Raul's terms).  Interspersed case values
seem to require very unnatural expression syntax.  If traditional control is
a goal then one needs controlled statements.

Kim Whitelaw, Andrew Seary, Bob Bernecky and many others have proposed or
argued for greater "functional" strength, and using that as a kind of control.
I believe, this will require a basic shift in programming method, which is one
possible reason why it hasn't been incorporated into APL (other than J, and
in a very limited way Dyalog APL) despite being around a very long time.

What I like about APL is its mixture of functional and imperative programming.
While I'd love to see its functional aspects strengthened, this should be
balanced by improving its imperative control.  (At the risk of starting a
war, I will say that pure functional programming is only a "niche".)
Block structure and traditional control are sorely needed.  What is not
obvious to the APL community, is that block structure is fundamental to
functional programming.  Without nested blocks one cannot talk scope;
without scope one cannot talk environment; without environment one cannot
seriously discuss closure and first-class objects.  APL has a single unnested
block structure, functions, and they are all thrown into a big _dynamically_
scoped workspace.  Direct definition BY ASSIGNMENT is UNSTRUCTURED, and will
require programming with great discipline (inconvenience) but will not offer
any of f.p.'s theoretical advantages (referential transparency; one still will
not be able to compile).  These "functional" proposals are fundamentally flawed
if they are not properly founded on nested structure.

Adding _structured_ direct definition/lambda expression/local function to APL
is a far more difficult problem than controlled statement or expression, and
frankly may never happen.  On the other hand, a limited "gosub" might handle
the simple cases quite nicely.  But my point remains, that we have at least
three different sets of goals and requirements, and trying to meet all three
with one unproven axe is not likely to succeed.  I think it is better to give
the implementors a choice of _complementary_ proposals; any one of these
should be quite useful, and more would be better.

Quote:
>---- (William Chang) writes:
>>Here are three orthogonal, complementary proposals for adding control
>>structures to APL.  Critiques are welcome.

>>(1) Controlled statements

>><WHILE>  {control} -> {block}
>><IF>     (control) -> {if-block} {optional-else-block}
>><CASE>   (control) -> (case1) {block1} ... (caseN) {blockN} () {default}

To answer Eke's question, the "control" is an expression to be compared
to case1,...,caseN, boolean if the case values are not given (0/1 by default).

Quote:
>>(2) Controlled expressions

>><EXPR>   {expr1} {expr2} ... {exprN} [control]

Again to answer Eke's question, each {expr} is evaluated bottom to top because
it is a single (left-tack separated) expression, not a collection of
statements.  This provides a clean way to do if, case, and for, by "indexing",
but would not (should not) be used for the indefinite while loop.  A design
decision here is what order to evaluate multiple {expr}'s; I chose ravel order.

Quote:
>>(3) Local functions and subroutines

>><GOSUB>  (control) -> label(val1;val2;...;valN)
>><DEFN>   label (arg1;arg2;...;argN) ;local1;...;localK : {block}
>><RETURN> <- optional-result
>I prefer the Manugistics control structures over these proposals
>for the following reasons:

>1) The resulting code is easier to read and understand (my opinion :)

Please elaborate.  (1) is not fundamentally different, except it allows the ->.

Quote:
>2) Manugistic's control structures are probably easier to implement.

Again, probably comparable to (1).

Quote:
>3) They are faster than branches with Manugistics implementation.
>4) The colon prefixed key words (especially with color highlighting) make
>   the structure of an algorithm apparent at a glance.

By the way, the dyadic usage of -> is based on the so-called "guarded command".

Quote:
>For the Manugistic's control structures, I dont like the following:
>1) IF statements require at least 3 statements (diamonds can separate the parts)
>       :if condition
>          statement
>       :endif
>   For the simple cases, I would prefer to write something like
>       :if condition :then statement  (i.e. BASIC's conventions)

This is what I mean by "rigid", requiring three precisely formatted lines
to do an if.  (Personally I have nothing against keywords; see my APL!.)
If they can be stringed on one line, then it would be pretty close to (1).

Quote:
>2) :GOTO and :RETURN seem useless.  :RETURN is not even as powerful as the
>   standard APL technique of branching to 0, since it is unconditional.

I think they are just disguised forms of the ->, "weak" by intention.

Quote:
>3) The control structures can only be used within functions

Again, blocks are not yet part of the language.

Can you write up a concise proposal for "first-class" blocks, that is perhaps
not based on unstructured assignment?  I think it would be useful.




Sun, 23 Feb 1997 00:41:08 GMT  
 Control Structures in APL

Quote:

>I have been following the discussion on control structures for some time, and have
>a few comments.  

>---- (Bernhard Strohmeier) writes:

>>The character set:
>>Do you really LIKE the J character set? J code looks as if somebody has
>>played tennis with the keyboard. J code is a complete MESS.

If you write a simple script, you can assign names as you desire to
the language elements. Also, I think we're seeing something in J which
happened in APL as well: tour de force programming: "How short can I make
this thing?" rather than the "how readable can I make this thing for others?"

Quote:
>>Who cares for control structures? I SWEAR that I will not even take a
>>look at APL*PLUSIII+n as long as they keep on including all this windows-
>>stuff, do-while loops, and OO-mickey-mouse-features, but neither complex
>>arithmetic nor adjustable numerical precision.

Although I'm a number jockey myself of late, I think you'll find your
position to be shared by few programmers. Maintainability features
such as control structures are important to all; complex arithmetic is
of utility to a much smaller audience.

Quote:

>1) The resulting code is easier to read and understand (my opinion :)
>2) Manugistic's control structures are probably easier to implement.
>3) They are faster than branches with Manugistics implementation.

>The resulting could possibly be slower in an "APL-ish" solution.

>Because of the function call overhead to plusrecip, this is actually 50% slower in
>Manugistics APL III, than a function that uses a for-loop.

Several posters in the above fragments are getting themselves in deep
here: They are presenting arguments about design based on speed of
a specific implementation. Design arguments should:

a. Ignore speed as an issue, and concentrate on the semantic and
   maintainability issues of the design.

b. Once a design has been agreed on, then and only then consider speed,
   BUT not in terms of the implementation of said design. Instead, the
   design should be critiqued on the basis of its computational
   complexity. For example, if one design is inherently n^3 in
   time/space complexity, it is Very Likely inferior in practice to
   one with n log n or n^2, performing a similar function.

Just because some vendor can't make all their code run Real Fast
at the same time is no reason to trash their design or a particular
coding style.

Bob



Sat, 22 Feb 1997 23:18:41 GMT  
 Control Structures in APL

Jeezus Murphy. Will you people PLEASE stop including the ENTIRE text
of previous postings in your stuff. Just include the relevant bits.
Or at least what you perceive to be the relevant bits.

Quote:
>We are at the mercy of the APL vendors--preprocessors are fine for testing
>out ideas, but are no good for real use, because of the complexities added
>to program development and debugging.

Note that the ability to invoke a STANDARD preprocessor, such as the
C preprocessor, would go a LONG way toward making development of large
systems in APL easier. Of course, in J, they can just use it, cuz
it's just plain ASCII.

Quote:
>other hand I believe there's a place for the "diamond" <> and traditional
>top to bottom flow.  My point is that the goals and requirements are different

 Ah, I love the innocents of the world. We, too, thought that diamond
was simple, easy to understand, etc. Now, go read something like
the new SHARP APL Reference Manual [or generic equivalent from other vendors]
and try to understand how diamond ties in with:
    trace/stop
    branching
    labels
    error trapping

It's a snakepit. No worse than C declarations, of course, but NOT
the kind of thing you want to take home to talk to Mom about.

Quote:
>clarify this basic distinction, between controlled expression and statement.
>While controlled expression may seem more general, it poses greater design
>and implementation problems.  It also seems more suited for the "definite" for

Upon what basis do make the "implementation problems" claim above?

Quote:
>Kim Whitelaw, Andrew Seary, Bob Bernecky and many others have proposed or
>argued for greater "functional" strength, and using that as a kind of control.
>I believe, this will require a basic shift in programming method, which is one
>possible reason why it hasn't been incorporated into APL (other than J, and
>in a very limited way Dyalog APL) despite being around a very long time.

I think you're missing the point. Functional strength does NOT
prohibit block-structuring. What it DOES do is encourage you to
write controlled loops which are functional: THey have arguments and
results. Side effects are not prohibited, BUT they are optional.
Imperative programming REQUIRES side effects. Evil, evil...
I'm saying "evil" from two perspectives:
   a. Side effects are harder to compile for efficient and/or parallel
      code.
   b. Side effects are harder to maintain: "Gee, why did that person
      write the code this way. I wonder if this variable is ever
      used... Hmmm, there MUST be some subtle reason for it..."

Quote:
>While I'd love to see its functional aspects strengthened, this should be
>balanced by improving its imperative control.  (At the risk of starting a
>war, I will say that pure functional programming is only a "niche".)
>Block structure and traditional control are sorely needed.  What is not
>obvious to the APL community, is that block structure is fundamental to
>functional programming.  Without nested blocks one cannot talk scope;

Huh? Who ever made the claim that functional programming and block
structure were different ends of the same stick?

Quote:
>without scope one cannot talk environment; without environment one cannot
>seriously discuss closure and first-class objects.  APL has a single unnested
>block structure, functions, and they are all thrown into a big _dynamically_
>scoped workspace.  Direct definition BY ASSIGNMENT is UNSTRUCTURED, and will

The workspace is certainly a mess. Compilers help here.

Quote:
>require programming with great discipline (inconvenience) but will not offer
>any of f.p.'s theoretical advantages (referential transparency; one still will
>not be able to compile).  These "functional" proposals are fundamentally flawed
>if they are not properly founded on nested structure.

Bull. (ABility to compile part). Functional stuff is EASIER to compile.

Bob



Sun, 23 Feb 1997 06:31:06 GMT  
 Control Structures in APL
 (William Chang in Marr Lab) writes:

Quote:
>What I like about APL is its mixture of functional and imperative programming.
>While I'd love to see its functional aspects strengthened, this should be
>balanced by improving its imperative control.

Manugistics did improve the imperative control in APL III IMHO; but their functional
programming aspects are weaker either than Dyalog APL or IBM APL2.

Quote:
>(At the risk of starting a
>war, I will say that pure functional programming is only a "niche".)
>Block structure and traditional control are sorely needed.  

Again the APL III control structures provide this.

Quote:
>...  Without nested blocks one cannot talk scope;
>without scope one cannot talk environment; without environment one cannot
>seriously discuss closure and first-class objects.  APL has a single unnested
>block structure, functions, and they are all thrown into a big _dynamically_
>scoped workspace.

I presume you mean lexically scoped definitions instead of APL's dynamically
scoped definitions.  Lexically scoped definitions are difficult to implement
efficiently in an interpreter (easier in a compiler). For closures with lexical
scoping, the interpreter must maintain an execution tree instead of a stack.

Quote:
>...
>>I prefer the Manugistics control structures over these proposals
>>for the following reasons:

>>1) The resulting code is easier to read and understand (my opinion :)

>Please elaborate.  (1) is not fundamentally different, except it allows the ->.

Consider the While loop
(a)
{control} -> {
  statement
  ...
  statement }

vs Manugistics
(b)
:WHILE control
  statement
  ...
  statement
:ENDWHILE

If I had never seen either control structure before, I would immediately understand
the meaning of (b).  I might be able to guess the meaning of (a).  Also, if the
control expression is complex, the structure of the algorithm in (b) is still apparent.

Quote:
>>2) Manugistic's control structures are probably easier to implement.

>Again, probably comparable to (1).

The implementation of the Manugistics :WHILE is simple since the :WHILE and :ENDWHILE must
occur at the beginning of a statement in a function; this is a very localized syntax extension.
Manugistics structures must be statically balanced; so the following is not allowed

->dum1
dum2:
:ENDWHILE
->0
dum1:
:WHILE control
  statement
  ->dum2

even though it is dynamically balanced.  The analysis of the control structure can thus be easily
performed at the time a function is saved (created).

Quote:

>Can you write up a concise proposal for "first-class" blocks, that is perhaps
>not based on unstructured assignment?  I think it would be useful.

OK, but I think we should also accept the Manugistics Control Structures (possibly with a few extensions).

My proposal is very similar other people's earlier proposals.
Assuming that we don't change APL scoping rules (APL name space problems are another topic), "first-class"
blocks are easy to add.  Semantically they would be similar to a null argument anonymous function or
a static string.  The monadic form of execute would be extended to accept blocks as well as strings.  If the
right argument to execute is a vector of blocks, then all blocks in the vector will be executed in left to
right order.  The default value for a block (e.g. in a take operation) would be a null block.  Scoping would
be dynamic (not lexical); so there are no problems with closures.

#del z<-condition THEN blocks
[1] z<-(1 0=condition)/2 #take blocks #del

#execute (A<B) THEN {X<-100}
#execute (A<B) THEN {X<-100} {Y<-100}

Note, the execute could be placed inside the THEN function; but then if the blocks use the parameter names
(condition or blocks) then we get unexpected results.

We could add local definitions to blocks with the syntax {;I;J; block-code} (I and J would be local to the block),
but this would make the implementation more difficult.

Blocks would be treated as immutable objects.  
Blocks would be also be useful for dealing with events.

So basically my proposal for blocks, is similar to what we already have with execute and strings, but
1) The syntax clearly indicates that executable code is associated with a block.
   - The block can be partially compiled (internally stored in a tokenized form).
   - Program analyzer tools can easily identify code (much more difficult when execute used with strings)
   - []LX<-{'Kim''s Stuff'} is more readable than []LX<-'''Kim''''s Stuff'''

2) The execute operator has been extended to accept a right argument that is an array of blocks.
   - Don't have to disclose or scalarize selection expressions.
   - Repeat block X 20 times is   #execute 20 #rho X

I'm not sure how to add lexical scoping to APL; or even if its a good idea.  It is difficult to implement.
There are already alternative solutions to the name space problem with IBM's mainframe implementation of APL2.



Sun, 23 Feb 1997 10:21:55 GMT  
 Control Structures in APL
Mike asks why we are discussing control structures.  Well I didn't start it :-)
On the other hand I have thought about it since high school, so can't keep my
mouth shut.  Yes, I can probably live with APL*PLUS III.  I would use the
:IF and :FOR, for multi-line stuff, and stick to my old one-line if and loop
->(&+1)-!ifnot <> ... <> ->&-!repeat, when appropriate.  I would continue to

can live with it.  

We will never be able to tell people that APL is elegant or beautiful, because
few of us would still believe it.

Mike also suggests:

Quote:
>Now, if we want to talk about changing the scope rules to allow
>block-local variables (which is a good idea) ... I would very much
>like to be able to write
>        :for;J;W;FUBAR J :in {iota}N
>          ... code ...
>        :endfor

Without facility for local functions, adding local block variables would be
nice but hardly a major improvement.  After all, it isn't hard to keep
track of names _within_ a function.  I would vote _against_ it.

Quote:
>There is no
>reason that control-structure keywords can't be properly internationalized.

Precisely.  I'd guess however that it would end up English by popular demand!

Quote:
>I agree with the sentiments that are
>going around, that it's time for _users_ to make an effort at deciding where
>APL should be going...
>I believe that e-mail is more than adequate as a medium for this sort of
>discussion.  The problem is getting organized.

I think a big problem is that c.l.a. and APL-L only reach a very small fraction
of APLers.  Although we are beginning to reach "critical mass" (when vendors
start to take us seriously--ha), unless everyone voice their opinion we will
continue to be ignored.  My attempt to funnel c.l.a. discussion (on ASCII) to
the Quote-Quad met with a bad end (despite heroic effort by then-ex-editor Bob
Brown), so it can be fairly assumed that what we discuss will never be read
by APLers at large.

(I have archived a few threads, available by anonymous ftp, at cshl.org
directory pub/bill/apl.)

Unlike the largely academic LISP community who tend to share ideas freely,
APL implementors will simply not give away their plans and secrets.  Unless
they increase their presence on c.l.a. and become more "open", we will never
know if our ideas are taken at all seriously.  Right now, they do a good job
describing their plans in the British Vector; perhaps such information can
appear in c.l.a. in a more timely manner, and be open to comments.

Finally, I have to add that Usenet news can be very unreliable.  I read APL-L
digests instead and post replies either through news (speedier) or the list.

Andrew writes something that I find very curious:

Quote:
>If blocks 'would be essentially be equivalent to an anonymous
>function with no arguments' it sounds like they would have to have
>side-effects to do anything useful.

I don't want to give a tutorial on this stuff, but the whole issue has to do
with what are called "free" or unbound variables.  "Functions" or blocks "use"
(or "affect") these free variables, in order to do useful things.  This is
absolutely a core issue of programming languages.  The basic question is,
should free variable refer to the calling environment (APL's dynamic scope)
or the definition environment (static scope, which coincides with lexical
scope for script-based languages).  The former makes compilation essentially
_impossible_, unless there are no free variables (which are needed of course to
do useful things).  Static/lexical scope sounds great, but largely irrelevant
in the context of a block-less, interpreted, persistent workspace based (i.e.
not script) language, because there is no concept of "nearest definition".  
To make local functions (aka lambda expressions aka direct definitions) really
useful, free variables must be resolved lexically in nested blocks.  Which is
why I said nested blocks are the foundation of functional programming.
Without nested blocks, direct definition (by assignment) is UNSTRUCTURED in
the worst possible ways (definition and use can be anywhere), and consequently
UNCOMPILABLE (can't resolve free variables).

Isn't the point of our discussion how to make APL structured?  Throwing in
function assignment (or function array) without well thought out restrictions
on its use can create a disaster.  At the very least, function variables should
be strictly local; so much for first-class.  Should a function variable be
available to a called subroutine?  An operator?  In whose environment should
(free) variables be resolved?

I believe this also addresses some of Bob's comments regarding compilability.
(I'm just glad he hasn't trashed my designs, yet.)  Bob also writes:

Quote:
>Note that the ability to invoke a STANDARD preprocessor, such as the
>C preprocessor, would go a LONG way toward making development of large
>systems in APL easier.

I agree, although even in C the preprocessor adds significant complexity to
program debugging (fortunately it takes away more).

Quote:
>Ah, I love the innocents of the world. We, too, thought that diamond
>was simple, easy to understand, etc.... try to understand how diamond ties
>in with: trace/stop   branching   labels   error trapping   It's a snakepit.


it would have been easier.  And about controlled expressions,

Quote:
>Upon what basis do make the "implementation problems" claim above?

For one, extrapolate the "diamond" problems to multi-line expressions or
looping/branching control structures that return results.  (Certainly not
insurmountable.)

Quote:
>I think you're missing the point. Functional strength does NOT
>prohibit block-structuring. What it DOES do is encourage you to
>write controlled loops which are functional: THey have arguments and
>results.

I'm not arguing against functional (really operator) strength, only when it's
done without block structuring, which must come first.

Quote:
>   a. Side effects are harder to compile for efficient and/or parallel code.

Possibly for parallel code.  For serial machine the opposite is clearly true.
Show me a better f.p. compiler than one for fortran or C.

Thank you for commenting!

Quote:

>(3) Local functions and subroutines

><GOSUB>  (control) -> label(val1;val2;...;valN)
><DEFN>   label (arg1;arg2;...;argN) ;local1;...;localK : {block}
><RETURN> <- optional-result

An alternative syntax for gosub is (val1;...;valN) -> label.  And now proposal

(4) Function and block variables

<LET>    f(arg1;...;argN);local1;...;localK <- {block}
<USE>    f(val1;...;valN)

Function variables are strictly local, and all free variables must be
resolved in the definition environment, i.e. must be local variables.
This ensures the referent of each free variable is known (to the extent
possible).  Function variables can be used in subroutine and operator calls,
but all free variables are bound in the definition environment (static scope).
Unlike J's tacit forms, function variables are not "ambivalent" (note syntax).

It is possible to allow nonlocal free variables, but they should be dynamically
bound in the definition environment (like other nonlocal variables), not in the
subroutine or operator environment.  (I think.  This is hardly trivial.)




Mon, 24 Feb 1997 00:59:43 GMT  
 Control Structures in APL
  (Andrew Seary) writes:

Quote:
>...
>>After all of this time, there still is no standard for APL control structures; yet
>>the language has changed in other significant ways (e.g. nested arrays).  

>Yup, and as significant, user-defined operators. These seem
>to be *almost neccessary* with nested arrays (they sure are handy).
>Thanks to APL2 for making these available.
>...
> Manugistics says they are moving towards APL2 syntax (I
>can't wait for N{take}[2] and ,[1 3] for example), but have not said
>anything about u-d-o's. Looks like the control words are supposed to be a
>replacement :-(  [any comment from MGSTSC?]

I also hope Manugistics will add the missing APL2 features such as
generalized axis operators and partition.

Quote:
>...
>I also coded your for-loop example (without using control words, of
>course, but it was rather straightforward). The result was about 10
>times *slower* than +{jot}{divide}/.

FYI, I coded the algorithm using conventional APL loops instead of APL III control
words.  The execution time was 2.5 times longer then the version using :FOR. (Which
is slower than the APL-ish solution).  I guess APL III has a inefficient implementation
of functions (lots of call overhead) and a  efficient implementation of For-loops

Quote:
>...
>a) I don't presently have access to APL*III (I'm in OS/2 so no Win32s
>   support; roll on Warp!)

If Warp supports Win32, VXD, OLE2, and Window for Workgroup networks, then
I'll give it a try.

Quote:
>b) DAPL doesn't have keywords, but then APL*III doesn't have
>   composition (or udo's). So it's hard to fairly compare them.

Hopefully, Manugistics will add support for both udo's and function composition.

Quote:

>Make that four problems. I object to having to decompile an APL
>expression so that compiler-oriented constructs can generate
>"efficient" code. If we are going to use Ada-(or other FBAP)style
>programming, why not just use Ada (or etc)?

I agree, I chose a poor example. I prefer the operator approach also;
but there are cases where the APL III control structures are useful.

Kim



Mon, 24 Feb 1997 01:09:49 GMT  
 Control Structures in APL

Quote:

>I have been following the discussion on control structures for some time, and have
>a few comments.  
>This discussion has been going on along time.  I have the proceedings of an APL conference
>that took place about 20 years ago in which APLGOL was discussed.  In this case, Algol like
>control structures were added to APL, and a preprocessor was used to compile the APLGOL code
>into APL.  After all of this time, there still is no standard for APL control structures; yet
>the language has changed in other significant ways (e.g. nested arrays).  

Yup, and as significant, user-defined operators. These seem
to be *almost neccessary* with nested arrays (they sure are handy).
Thanks to APL2 for making these available.

[...deletia...]

Quote:
>I've used the windows-stuff in APL*PLUS III to build a database application.  The interface isn't
>quite as polished as Visual Basic, but the application was much easier to write.  It was nice to
>be able to manipulate the entire contents of a list box at once.  The Windows environment provides
>a very nice programming environment, better than any other APL I've used.

I agree. It's a wonderful *environment*, but the implementation is
lacking some important things (namely u-d-o's, but also complex
numbers). Manugistics says they are moving towards APL2 syntax (I
can't wait for N{take}[2] and ,[1 3] for example), but have not said
anything about u-d-o's. Looks like the control words are supposed to be a
replacement :-(  [any comment from MGSTSC?]

[...more deletia...]

Quote:

>>I think J is showing the way (or was): operators as control
>>structures, along with function assignment and  "nonce functions",
>>(using { and } as delimiters for APL) and function arrays (gerunds).
>>I don't see why we can't put this functionality in APL2. A lot of it
>>is already in Dyalog APL.
>I agree; I would especially like to see J's ability to compose functions added to APL.
>>With these in place, the operater-style control structures can allow
>>for multiple, parallel, independent "function" execution, based on
>>possible *vector* controls. This seems much more "APL-ish" than
>>control words.
>The resulting could possibly be slower in an "APL-ish" solution.
>Consider the problem of evaluating a n element continued fraction f
>  f[1] + {divide} f[2] + {divide} f[3] + {divide} ... + {divide} f[n]
>In J, because functions can be composed, we can simply write:
>   (+%)/f    e.g. (+%)/1 2 2 2 2 2 2 2 2    returns  1.41421
>In Manugistics APL, If we define a function plusrecip
>   {del} z <- a plusrecip b
>   [1] z <- a plusrecip b
>   {del}
>then we can evaluate the continued fraction by   plusrecip / f
>for example:   plusrecip / 1 2 2 2 2 2 2 2 2
>returns a close approximation to the square-root of 2.
>Because of the function call overhead to plusrecip, this is actually 50% slower in
>Manugistics APL III, than a function that uses a for-loop.
>   [1] z <- {take} f <- {reverse} f
>   [2] :for i :in 1 {drop} f
>   [3]   z <- i + {divide} z
>   [4] :endfor

I think this is an implementation issue.
For example, in Dyalog APL I can write:
+{jot}{divide}/1 2 2 2 2 2 2 2
Where {jot} is the composition operator.

I can also *define* a composition operator:
[0]Z<-X(F c G)Y
[1]Z<-X F G Y (and of course, this is also possible in APL2)

I tried your examples in DAPL/UNX on t<-?10000{rho}1000 and got the
following results:
+{jot}{divide} was twice as fast as plusrecip. c was slightly slower
than plusrecip. (It's hard to time exactly on Unix).
I also coded your for-loop example (without using control words, of
course, but it was rather straightforward). The result was about 10
times *slower* than +{jot}{divide}/.

Yes, I know this is not fair, but
a) I don't presently have access to APL*III (I'm in OS/2 so no Win32s
   support; roll on Warp!)
b) DAPL doesn't have keywords, but then APL*III doesn't have
   composition (or udo's). So it's hard to fairly compare them.

And note that I spoke of "functions" in quotes -- they could be
funargs like +{jot}{divide}, which DAPL seems to handle rather well.
Or "anonymous functions" which we don't yet have in any APL, but do
have in J  (also called "nonce functions" in APL). Or function arrays.

MGSTSC seems to have concentrated on making the keyword-controls fast
whereas DAPL has concentrated on making derived functions fast.
I'd try this in APL232/PC, but it is in the middle of a long computation...

Quote:

>>I have three problems with this (APL*III)
>>1) *english* reserved words (redefinable in J?)
>The *english* reserved words are similar to the ones used in conventional languages
>(e.g. Ada).  Its likely that most APL programmers could easily understand code that uses
>the Manugistics control stuctures; even if they haven't seen them before.  This is
>probably not true for the other control structure suggestions.

Make that four problems. I object to having to decompile an APL
expression so that compiler-oriented constructs can generate
"efficient" code. If we are going to use Ada-(or other FBAP)style
programming, why not just use Ada (or etc)?

I use APL because I don't want to waste a lot of time programming.

Quote:
>I still like the idea of adding blocks {...} to APL as first class objects, and having
>the execute operator accept blocks as well as strings.  A block would essentially be
>equivalent to an anonymous function with no arguments.  Potentially, blocks can be
>implemented more efficiently than strings, since they can be stored in a tokenized form.

No, no, not execute! It should be a true inverse to format! (especially
format by example -- plug).
(but...well...hmmm, so format replaces {quad}CR on functions...hmmm).

If blocks 'would be essentially be equivalent to an anonymous
function with no arguments' it sounds like they would have to have
side-effects to do anything useful. However, you could just use (anonymous)
functions (with operators), and ignore the arguments to get the same effect.

Quote:
>Kim

I like the operator approach, since we don't have to multiply entities
unneccessarily: we already have operators. And it gives some impetus
to "finishing" the objects available in APL -- function assignment,
function arrays, anonymous functions -- and functions become first-class
objects. I think we have been talking about *this* for 20 years, too.




Fri, 21 Feb 1997 03:21:15 GMT  
 Control Structures in APL
 (William Chang in Marr Lab) writes:

Quote:
>Isn't the point of our discussion how to make APL structured?  Throwing in
>function assignment (or function array) without well thought out restrictions
>on its use can create a disaster.  At the very least, function variables should
>be strictly local; so much for first-class.  Should a function variable be
>available to a called subroutine?  An operator?  In whose environment should
>(free) variables be resolved?

(free) variables should be resolved in under the environment in which the function
is executed (i.e. the dynamic environment).  I realize this can lead to erroneous code,
but this is the way that APL works.  Currently local variables in a function are visible
to all functions that the function calls.  Changing this could break exitsting code.

Quote:

>>(3) Local functions and subroutines

>><GOSUB>  (control) -> label(val1;val2;...;valN)
>><DEFN>   label (arg1;arg2;...;argN) ;local1;...;localK : {block}
>><RETURN> <- optional-result

>An alternative syntax for gosub is (val1;...;valN) -> label.  And now proposal

>(4) Function and block variables

><LET>    f(arg1;...;argN);local1;...;localK <- {block}
><USE>    f(val1;...;valN)

(4) seems more natural then (3), but how do you return a result. Why not use
standard APL syntax for function definitions within functions, i.e. use del to
begin and end nested functions.  The interpreter would simply skip over a functions
it encounters.
#del OUTER
[1] #del z<-INNER A;B
[2] B_statement1
[3] Z<-B_statement2 #del
[4]
[5] INNER 10 * INNER 20
#del

Quote:
> (4) continued...
>Function variables are strictly local, and all free variables must be
>resolved in the definition environment, i.e. must be local variables.

The ability to declare and use strictly local variables would be very useful.  This
could be efficiently accomplished by interning the local names into a unique name
space associated with the function at the time it is saved.  The syntax for
specifying strictly local variables should be different then the current APL syntax
for specifying local (free) variables.  One possibility is require that strictly
local variables have a special prefix character (like &); then the programmer could
easily distinguish between variables with different scope classes; and existing APL
code would not break.  

Kim



Mon, 24 Feb 1997 10:18:38 GMT  
 Control Structures in APL

Quote:

>>   a. Side effects are harder to compile for efficient and/or parallel code.

>Possibly for parallel code.  For serial machine the opposite is clearly true.
>Show me a better f.p. compiler than one for FORTRAN or C.

I concur with most of the points you make in your recent postings
partially copied here, but I suggest you look at SISAL for a good
F.P. Compiler. See an article by David Cann in an issue of CACM about
a summer or two ago: "Retire Fortran: A debate Rekindled". Cann shows
a number of non-trivial benchmarks in which relatively straightforward
SISAL beats Fortran on several large applications on supercomputers.

The problems the SISAL crew is solving are exactly the same sorts of things
APL compiler writers face. APLers actually have it harder [ at least,
I do this week...] because of messes like:
  - no control structures
  - non-functional control structures [rather than "for" loops which
    return a result, etc, forcing use of side effects]
  - globals and semi-globals.

Bob



Mon, 24 Feb 1997 10:28:50 GMT  
 Control Structures in APL

Quote:

> (William Chang in Marr Lab) writes:
>>Isn't the point of our discussion how to make APL structured?  Throwing in
>>function assignment (or function array) without well thought out restrictions
>>on its use can create a disaster.  At the very least, function variables should
>>be strictly local; so much for first-class.  Should a function variable be
>>available to a called subroutine?  An operator?  In whose environment should
>>(free) variables be resolved?

>(free) variables should be resolved in under the environment in which the function
>is executed (i.e. the dynamic environment).  I realize this can lead to erroneous code,
>but this is the way that APL works.  Currently local variables in a function are visible
>to all functions that the function calls.  Changing this could break exitsting code.

I was talking about static scope for _local_ functions only.  Let me give an
example.  When a function F calls another function G, F's variables are what
they are.  G's (local) variables cannot shadowing F's.  But when a _local_
function F1 _inside_ F is dynamically scoped, this is no longer true.  A name
in F1, including all function and operator names, can be shadowed if G calls
F1, even though the name sits happily inside F which is above G.

Thus one cannot be sure F1 is what it looks like without looking at all of F's
function calls, even if they are known to be side-effect free.  And similarly
so if F1 is passed to a user-defined operator.  This is called loss of
"referential transparency" and would make dynamic scoping far more dangerous
(ugly) than it currently is.

I strongly believe that names inside a local function (or direct definition
or gerund etc.) should be resolved within its lexical context.  Otherwise there
would be no (structured programming) rationale for it, other than (dangerous)
convenience.

Gotos at least can't jump into the middle of another function.  A badly
designed "first class" local function would mean exactly that.

An obvious use of a _statically_ scoped local function is exception handling.
The local function F1 would "catch", and a function G called by F would "throw"
an exception by calling F1.  A branch (not return) out of F1 will exit G.

This proposal appears to me to be useful (structured) and pretty much in
keeping with current APL syntax, style, and spirit.




Mon, 24 Feb 1997 23:22:44 GMT  
 Control Structures in APL

y

Quote:
>Mike asks why we are discussing control structures.  Well I didn't start it :-)
>On the other hand I have thought about it since high school, so can't keep my
>mouth shut.  Yes, I can probably live with APL*PLUS III.  I would use the
>:IF and :FOR, for multi-line stuff, and stick to my old one-line if and loop
>->(&+1)-!ifnot <> ... <> ->&-!repeat, when appropriate.  I would continue to

>can live with it.  
>We will never be able to tell people that APL is elegant or beautiful, because
>few of us would still believe it.

Exactly!

Quote:
>>There is no
>>reason that control-structure keywords can't be properly internationalized.
>Precisely.  I'd guess however that it would end up English by popular demand!

Ok. Replace "English" with "verbose". Make that "clunky and verbose".

[#delta a *lot* of line numbers. Murphy Jeezus would be proud.]

Quote:
>Andrew writes something that I find very curious:
>>If blocks 'would be essentially be equivalent to an anonymous
>>function with no arguments' it sounds like they would have to have
>>side-effects to do anything useful.

Umm. I was quoting Kim Whitelaw, hence the quotes. Guess I should have
used { and }.

Quote:
>I don't want to give a tutorial on this stuff, but ...

[ very useful tutorial deleted ]

I am thinking of what's inside the {}'s as J tacit functions. Possibly
I should go back and look at what's inside others' {}'s.

Quote:
>Isn't the point of our discussion how to make APL structured?  Throwing in
>function assignment (or function array) without well thought out restrictions
>on its use can create a disaster.  At the very least, function variables should
>be strictly local; so much for first-class.  Should a function variable be
>available to a called subroutine?  An operator?  In whose environment should
>(free) variables be resolved?

I must have completely missed where "function variables" were defined.
Just grep-ed my copy of apl-l and couldn't find it. If you mean "nonce
functions"( or J's tacit functions), then:
Function assignment works quite well in J and Dyalog APL. Function
arrays (as in gerunds) work quite well in J, and could be added to APL
without changing the language essentials. So could nonce functions (a
seperate issue). You can assign a local nonce function and use it in a
sub-function in DAPL. Such an assigned function can be used with an
operator. Free variables are attached to them by the usual APL syntax.
The last two statements also apply to anonymous (unassigned, true
nonce) functions.
Also, FWIW, DAPL allows you to store the #OR of a function (could be a
nonce function) anywhere in any array. This is not just the character
representation, or at least it isn't treated this way. What could this
be used for? Dunno, but I guess Dyalog has *their* theorists, too.

Quote:
>Bob Bernecky writes:
>>.... Functional strength does NOT
>>prohibit block-structuring. What it DOES do is encourage you to
>>write controlled loops which are functional: THey have arguments and
>>results.

I pretty much agree. I must be more influenced by J than I thought! :)




Mon, 24 Feb 1997 05:57:50 GMT  
 
 [ 29 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Proposal for control structures in APL

2. Proposal for control structures in APL

3. Proposal for control structures in APL (SAMSON)

4. Control Structures in APL

5. Control structures in APL

6. Control structures in APL

7. Control structures in APL

8. control structures in APL

9. Control Structures in APL

10. Control structures in APL

11. APL Control Structures

12. APL control structures -- new

 

 
Powered by phpBB® Forum Software