Readability: Difference between revisions
(→IBM) |
|||
Line 17: | Line 17: | ||
=== IBM === | === IBM === | ||
The [[APL2]] | The [[idiom]] list included with [[APL2]] includes the following entry:<ref>Cason, Stan. [ftp://ftp.software.ibm.com/ps/products/apl2/info/APL2IDIOMS.pdf#page=3 APL2 IDIOMS Library]. IBM.</ref> | ||
:{| style=width:100% | :{| style=width:100% | ||
|<source lang=apl inline>X←'line1',0⍴Y←'line2'</source>||<source lang=apl inline>⍝ Pornography. Combining two lines into one.</source> | |<source lang=apl inline>X←'line1',0⍴Y←'line2'</source>||<source lang=apl inline>⍝ Pornography. Combining two lines into one.</source> | ||
|} | |} | ||
This was a common technique before [[Left]] | This was once a common technique before, even though it is prone to fail in where the value to the left of <source lang=apl inline>,0⍴</source> isn't a vector, for example in the following example where <source lang=apl inline>X</source> becomes a 1-element [[vector]] instead of the intended [[scalar]]: | ||
<source lang=apl> | |||
X←'l',0⍴Y←'line2' | |||
Y∘.=X | |||
1 | |||
0 | |||
0 | |||
0 | |||
0 | |||
</source> | |||
With the addition of [[Left]] (<source lang=apl inline>⊣</source>) to the language, this type of hack became became entirely obsolete: | |||
:<source lang=apl inline>X←'line1' ⊣ Y←'line2'</source> | :<source lang=apl inline>X←'line1' ⊣ Y←'line2'</source> | ||
The primitive leaves its left argument unmodified: | |||
<source lang=apl> | |||
X←'l' ⊣ Y←'line2' | |||
Y∘.=X | |||
1 0 0 0 0 | |||
</source> | |||
The Diamond [[statement separator]] (<source lang=apl inline>⋄</source>) provides an alternative means of inlining multiple statements: | The Diamond [[statement separator]] (<source lang=apl inline>⋄</source>) provides an alternative means of inlining multiple statements: | ||
:<source lang=apl inline>Y←'line2' ⋄ X←'line1'</source> | :<source lang=apl inline>Y←'line2' ⋄ X←'line1'</source> | ||
Note that in all | Note that in all the above, <source lang=apl inline>Y</source> is assigned first. | ||
=== Morten Kromberg === | === Morten Kromberg === |
Revision as of 08:17, 27 September 2020
Maintaining readability of APL can take a special effort. It is easy to write very dense code, and the mathematical look of APL can encourage usage of single-letter names. Traditionally, APLers use the term pornography to describe code that is hard to read, or uses unusual constructs. Code golf often results in pornographic code.
Examples
Gilman & Rose
In APL ― An Interactive Approach, the authors describe the following code, which computes the correlation coefficient, as “almost pornographic”:
r←(+/x×y)÷((+/(x←x-(+/x)÷⍴x)*2)×+/(y←y-(+/y)÷⍴y)*2)×.5
By splitting the expression intro even a moderate number of pieces, a symmetry is revealed:
yVar←+/(y-(+/y)÷⍴y)*2 xVar←+/(x-(+/x)÷⍴x)*2 r←(+/x×y)÷(xVar×yVar)×0.5
This also avoids reusing variable names, and thus ensures that the code can be rerun from any point. The chosen additional variable names are still short, but quite indicative of what they signify (variance). Finally, the .5
is expanded to 0.5
which helps to clarify that this is a decimal number and not an inner product.
A more modern approach breaks out the symmetry into a utility function train, and uses leading axis theory combined with operators and reordering of terms to avoid parentheses (which would otherwise require a mental stack to understand). Finally, the correlation coefficient is defined as a stand-alone function, using inner product to combine summation with multiplication
Var←+/2*⍨⊢-+⌿÷≢ R←2×+.×÷×⍥Var r←x R y
Note that +⌿÷≢
is an idiom (common phrase) and is read as average by even moderately experienced APL programmers.
IBM
The idiom list included with APL2 includes the following entry:[1]
X←'line1',0⍴Y←'line2'
⍝ Pornography. Combining two lines into one.
This was once a common technique before, even though it is prone to fail in where the value to the left of ,0⍴
isn't a vector, for example in the following example where X
becomes a 1-element vector instead of the intended scalar:
X←'l',0⍴Y←'line2' Y∘.=X 1 0 0 0 0
With the addition of Left (⊣
) to the language, this type of hack became became entirely obsolete:
X←'line1' ⊣ Y←'line2'
The primitive leaves its left argument unmodified:
X←'l' ⊣ Y←'line2' Y∘.=X 1 0 0 0 0
The Diamond statement separator (⋄
) provides an alternative means of inlining multiple statements:
Y←'line2' ⋄ X←'line1'
Note that in all the above, Y
is assigned first.
Morten Kromberg
Morten Kromberg asked one of his colleagues to “Please avoid this kind of pornography:”
ns(⍎container.⎕NS)←⍬
Avoiding the unusual modified assignment (using the 2-train ⍎⎕NS
as modifying function) helps:
ns←ns container.(⍎⎕NS) ⍬
Finally, splitting the 2-train apart makes it even clearer:
ns←⍎ns container.⎕NS ⍬
A new namespace, with the original value of ns
as name, is created inside container
and the character representation '#.container.ns'
is returned from ⎕NS
to ⍎
which evaluates the name to a reference, that in turn replaces the previous value of ns
.
See also
- ↑ Cason, Stan. APL2 IDIOMS Library. IBM.